Reputation: 4568
I am really stuck on this. I'm clearly not understanding the MIN/MAX concept.
I am trying to get the latest row from a grouping of work_type and work_id.
If I change from MIN to MAX, it changes the returned timestamp, but it never brings the status info from that record.
Example:
"SELECT
CONCAT(work_type, work_id) AS condition_id,
status,
MIN(created_timestamp) as latest
FROM conditions
GROUP BY condition_id"
With MIN, I get:
Array
(
[0] => Array
(
[condition_id] => cutouts00002
[status] => bad
[latest] => 2011-02-21 15:20:27
)
[1] => Array
(
[condition_id] => paintings00002
[status] => damagez
[latest] => 2011-02-21 14:43:35
)
)
With MAX I get:
Array
(
[0] => Array
(
[condition_id] => cutouts00002
[status] => bad
[latest] => 2011-02-21 15:22:20
)
[1] => Array
(
[condition_id] => paintings00002
[status] => damagez
[latest] => 2011-02-21 14:43:41
)
)
Bu the thing is that the status in the row with the latest timestamp, is "no damage", but it never returns the row corresponding to the MAX(current_timestamp), it only ever returns the "damagez" row.
Any help is appreciated.
Thanks.
Upvotes: 3
Views: 3668
Reputation: 11832
I would prefer putting the subquery in the WHERE clause, as it reads easier.
SELECT
CONCAT(work_type, work_id) AS condition_id,
status,
created_timestamp as latest
FROM
conditions
WHERE
created_timestamp = (
SELECT
MIN(conditions2.created_timestamp)
FROM
conditions AS conditions2
WHERE
conditions2.condition_id = conditions.condition_id
)
GROUP BY
condition_id
Also, if the first query was to have any additional join or where clauses, they can be repeated in the subquery.
SELECT
CONCAT(work_type, work_id) AS condition_id,
status,
created_timestamp as latest
FROM
conditions
INNER JOIN some_table on condition.id = some_table.condition_id
WHERE
some_table.some_column > 50 AND
created_timestamp = (
SELECT
MIN(conditions2.created_timestamp)
FROM
conditions AS conditions2
INNER JOIN some_table AS some_table2 on condition2.id = some_table2.condition_id
WHERE
some_table.some_column > 50 AND
conditions2.condition_id = conditions.condition_id
)
GROUP BY
condition_id
Upvotes: 0
Reputation: 107716
You have fallen prey of the MySQL lax rules that allow for non-aggregates to be included in a GROUP BY query. Sure, you are working with MIN or MAX, and only ONE at a time, but consider this query:
SELECT
CONCAT(work_type, work_id) AS condition_id,
status,
MIN(created_timestamp) as earliest,
MAX(created_timestamp) as latest
FROM conditions
GROUP BY condition_id
Now, think about which row the status column should come from. It's absurd to put a correlation between the aggregate (those in the GROUP BY) and non-aggregate columns.
Instead, write your query like this
SELECT X.condition_id, C.status, X.earliest
FROM (
SELECT
CONCAT(work_type, work_id) AS condition_id,
status,
MIN(created_timestamp) as earliest
FROM conditions
GROUP BY condition_id
) X JOIN conditions C
on CONCAT(c.work_type, c.work_id) = X.condition_id
and c.created_timestamp = X.earliest
But if you had two records with the same created_timestamp, it gets even more tricky
SELECT X.condition_id, Max(C.status) status, X.earliest
FROM (
SELECT
CONCAT(work_type, work_id) AS condition_id,
status,
MIN(created_timestamp) as earliest
FROM conditions
GROUP BY condition_id
) X JOIN conditions C
on CONCAT(c.work_type, c.work_id) = X.condition_id
and c.created_timestamp = X.earliest
GROUP BY X.condition_id, X.earliest
Upvotes: 2
Reputation: 2199
I've generally had to do something quite icky for that.
My solution is T-SQL, but I hope you can rework it.
SELECT
CONCAT(c.work_type, c.work_id) as condition_id,
c.status,
c.created_timestamp as latest
FROM conditions c
JOIN (SELECT work_type, work_id, max(current_timestamp) as latest GROUP BY work_type, work_id) c2
ON c.work_type = c2.work_type
AND c.work_id = c2.work_id
AND c.created_timestampe = c2.latest
Upvotes: 0