I am trying to use a max(..) to get the maximum value from a set, but I want to also get the other row values that correspond to this row (or rows if there are multiple rows that match the same "max"). I’m using MySQL 8.
I was able to part of the way using this SQL (a solution provided by SelVazi in this related post: Get value from the same row as an aggregate function (max) in MySQL using SELECT query)
However, now things have gotten more complicated. I’m splitting tasks into a separate table, so that I only need to save the task ID values in the "user_tasks" table.
In situations where there are multiple tasks with the same "max" datetime, I’d like to have all those task names listed in the result set (with task_duration values)
This is the SQL that I’m currently working with:
SELECT u.*
FROM user_tasks u
INNER JOIN (
SELECT user_id, max(login_time) as last_login_time, task_duration
FROM user_tasks
WHERE user_id IN (123, 456, 789)
group by user_id
) AS s ON s.user_id = u.user_id and s.last_login_time = u.login_time;
Here is the DB schema & some sample values:
create table user_tasks (
user_id int(11),
login_time datetime,
task_id int(11),
task_duration int(11)
)
create table tasks (
task_id int(11),
task_name varchar(50)
)
insert into user_tasks values (123, '2023-01-30 06:10:03', 1, 50);
insert into user_tasks values (123, '2023-02-25 06:10:03', 2, 45);
# please note below there are duplicate date values (so both are "max")
insert into user_tasks values (123, '2023-05-30 06:10:03', 3, 60);
insert into user_tasks values (123, '2023-05-30 06:10:03', 2, 20);
insert into user_tasks values (456, '2023-03-30 06:10:03', 3, 50);
insert into user_tasks values (456, '2023-02-25 06:10:03', 1, 20);
insert into user_tasks values (456, '2023-01-30 06:10:03', 2, 10);
insert into user_tasks values (789, '2023-03-30 06:10:03', 3, 35);
insert into user_tasks values (789, '2023-01-30 06:10:03', 1, 38);
insert into user_tasks values (789, '2023-05-30 06:10:03', 2, 26);
insert into user_tasks values (898, '2023-05-30 06:10:03', 1, 16);
insert into user_tasks values (900, '2023-05-30 06:10:03', 2, 18);
# and now, the tasks table...
insert into tasks values (1, 'walk dog');
insert into tasks values (2, 'bathe dog');
insert into tasks values (3, 'feed dog');
The above SELECT statement yields this result:
123,'2023-05-30 06:10:03', 3, 60
123,'2023-05-30 06:10:03', 2, 20
456,'2023-03-30 06:10:03', 3, 50
789,'2023-05-30 06:10:03', 2, 26
However, I would like it to yield this result:
123,'2023-05-30 06:10:03','feed dog', 60
123,'2023-05-30 06:10:03','bathe dog', 20
456,'2023-03-30 06:10:03','feed dog', 50
789,'2023-05-30 06:10:03','bathe dog', 26
Also, if anyone can think of a better title for this post, please suggest one and I’ll gladly edit it to better reflect the question. Thanks!
2
Answers
The best way to do this in modern MySQL 8.0 or later is to use a window function:
Result given your test data:
If you’re not using a version of MySQL that supports window functions, it’s time to upgrade. All MySQL 5.x versions have passed their end-of-life date.
Just join on the additional table…
Or more concisely…