The only reason that query works at all is because MySQL is mildly brain-dead.
Any other DB would insist that your GROUP BY clause read
Code:
GROUP BY users.user_id,users.firstname,users.middlename,users.lastname,user_shift_schedule.shift_id
But MySQL allows you to omit one or more of the normally required fields.
The problem is, when it does so, it RANDOMLY PICKS the value for the fields that you did *NOT* specify.
To create a simpler example, let's just show with 3 fields in the select.
First, let's show the records you would have without the GROUP BY:
Code:
user_id | shift_id | effectivity_date
17 | 2 | Jan 1
17 | 2 | Feb 1
17 | 3 | Mar 1
17 | 3 | Apr 1
Now, when you do
Code:
SELECT user_id, shift_id, MAX(effectivity_date) ... GROUP BY user_id
MySQL produces this:
Code:
user_id | shift_id | effectivity_date
17 | 2 or 3 | Apr 1
You see? You have *NOT SPECIFIED* which
shift_id you want, so MySQL feels free to pick ANY ONE THAT IS AVAILABLE. Usually, it will simply pick the first one it finds (but that's not universal), so that's why you get back
Code:
user_id | shift_id | effectivity_date
17 | 2 | Apr 1
*IF* you had properly coded
Code:
SELECT user_id, shift_id, MAX(effectivity_date)
... GROUP BY user_id, shift_id
*THEN* MySQL would give you the correct results (as would any other DB):
Code:
user_id | shift_id | effectivity_date
17 | 2 | Feb 1
17 | 3 | Apr 1
In other words, now you get TOO MANY results. But that's what the DB *should* be giving you.
The right answer is to ALWAYS use the proper GROUP BY (that is, include *all* fields that are not part of an aggregate function--MAX, MIN, AVG, COUNT, etc.) but then fix the query in other ways.
Code:
SELECT U.user_id, U.firstname, U.middlename, U.lastname, S.shift_id, S.effectivity_date
FROM users AS U,
user_shift_schedule AS S,
( SELECT user_id, MAX(effectivity_date) AS maxDate
FROM user_shift_schedule
GROUP BY user_id ) AS M
WHERE U.user_id = S.user_id
AND S.user_id = M.user_id
AND S.effectivity_date = M.maxDate
Now, this is still not perfect. If there happen to be *TWO* effectivity_date values that are the same as MAX(effectivity_date) for the given user_id, then you *will* get two records.
How you break a "tie" like that depends on other data in the tables, and you haven't given me enough to go on to know (a) whether you will need to break ties and/or (b) how to do so if needed.