Reputation: 722
I want to join two tables namely staff and staff exam time tables. A staff can attend N number of Exams. My result should be staff id, staff name, end time of the last completed exam.
My Table structure is below
staff table
staff_id staff_full_name staff_status
500 Sakthi active
550 Siraj active
600 Shihab K H active
620 John David active
670 Javed Akthar active
examtime table
examtime_id examtime_staffid examtime_endtime
100 500 2014-10-10
101 600 2016-05-01
102 670 2016-06-10
103 670 2014-04-01
104 670 2016-06-13
105 670 2016-06-11
SQL QUERY FOR THE RESULT SET IS BELOW
SELECT S.staff_id, S.staff_full_name, ET.examtime_endtime
FROM staffs S LEFT JOIN examtime ET ON ET.examtime_staffid = S.staff_id
WHERE 1 AND S.staff_status = 'active' GROUP BY S.staff_full_name ORDER BY S.staff_full_name ASC , ET.examtime_endtime DESC
But I am getting the result set as below. It is fetching the first record of the exam time table irrespective of the exam end time. See below Result set ( Javed Akthar Latest exam date is 2016-06-13 but it is fetching 2016-06-10 ).
500 Sakthi 2014-10-10
600 Shihab KH 2016-05-01
670 Javed Akthar 2016-06-10
Upvotes: 3
Views: 4011
Reputation: 40481
The problem is with your GROUP BY
clause, you didn't specify which date you want for each one, so it is randomly selecting one, not necessarly the maximum one.
You can find a good explanation about this behaviour here in @mjv answer
Try this query:
SELECT S.staff_id, S.staff_full_name, max(ET.examtime_endtime) as max_endTime
FROM staffs S
LEFT JOIN examtime ET
ON (ET.examtime_staffid = S.staff_id)
WHERE S.staff_status = 'active'
GROUP BY S.staff_id ,
S.staff_full_name
ORDER BY S.staff_full_name ASC ,
max_endTime DESC
It will select the maximum date for each staff_id
and will order by it. In general - it is common to specify all the columns that represent each group(in this case staff_id,staff_full_name
) in the GROUP BY
clause and all other columns with an aggregation function(AVG/MAX/MIN
..) , this will help you avoid this kind of problems in the future.
Upvotes: 3
Reputation: 239664
If you just want the most recent exam time for each staff and don't require any other columns from that table, you can do this with standard SQL and avoid the hazard you've introduced by using a MySQL "extension" (wherein you can have columns that aren't in aggregates and aren't in the GROUP BY
and MySQL selects an arbitrary value for that column):
SELECT MIN(S.staff_id) as staff_id,
S.staff_full_name,
MAX(ET.examtime_endtime) as examtime_endtime
FROM staffs S LEFT JOIN examtime ET ON ET.examtime_staffid = S.staff_id
WHERE S.staff_status = 'active'
GROUP BY S.staff_full_name
Upvotes: 1