I want to get the last record of each user for each category.
eg I have a table
tests (test_id,cat_id,user_id,score,time)
I need each user last record for each category. I can use group by either category_id or by user_id but I am not getting how to get my desired result?
eg I have following records
test_id | cat_id | user_id | score | time
1 | 1 | 11 | 20 | 2016-11-12 01:11:11
2 | 2 | 11 | 24 | 2016-11-12 01:11:11
3 | 1 | 12 | 25 | 2016-11-12 01:11:11
4 | 3 | 12 | 21 | 2016-11-12 01:11:11
5 | 1 | 13 | 22 | 2016-11-12 01:11:11
6 | 2 | 12 | 23 | 2016-11-12 01:11:11
7 | 2 | 12 | 27 | 2016-11-12 01:11:11
8 | 1 | 11 | 21 | 2016-11-12 01:11:11
Now I need following result
test_id | cat_id | user_id | score | time
2 | 2 | 11 | 24 | 2016-11-12 01:11:11
3 | 1 | 12 | 25 | 2016-11-12 01:11:11
4 | 3 | 12 | 21 | 2016-11-12 01:11:11
5 | 1 | 13 | 22 | 2016-11-12 01:11:11
7 | 2 | 12 | 27 | 2016-11-12 01:11:11
8 | 1 | 11 | 21 | 2016-11-12 01:11:11
In above o/p each user's only last result is coming of each category.
The query you need is:
SELECT l.test_id, l.cat_id, l.user_id, l.score, l.time
FROM tests l # "l" from "last"
LEFT JOIN tests n # "n" from "next"
ON l.user_id = n.user_id # match user
AND l.cat_id = n.cat_id # and category
AND l.time <= n.time # "next" is not before "last" (check the time)
AND l.test_id < n.test_id # "next" is after "last" when the times are equal
WHERE n.test_id IS NULL # there is no "next" matching the JOIN conditions
The query joins test
aliased as l
(from "last") against itself aliased as n
(from "next" after "last"). The LEFT JOIN
ensures that all the rows from l
are included in the join. Each row from l
is paired with all the rows from n
that contain the same user_id
and cat_id
("each user, each category") and have greater values in columns time
and test_id
. Because it's technically possible to have two rows with the same values in columns user_id
, cat_id
and time
, on equal times match the row from l
with a row from n
that was input in the database later (it has a bigger auto-incremented test_id
).
When a row that fulfills all the ON
conditions is not found in n
, the row from l
is paired with a row full of NULL
s.
The WHERE
condition keeps only the rows having NULL
in n.test_id
. They are the rows from l
that don't have a match in n
(because there is no row in n
having a bigger value in the time
column or a bigger test_id
when the times are equal). These are the last records for each (user, category) pair.
试试这个SELECT MAX(user_id) FROM tests GROUP BY cat_id
Here we need a last user for all categories. SO we have to do group by category and find the user which have highest time for it.
SELECT t1.*
FROM tests t1
INNER JOIN
(
SELECT max(time) MaxTime,user_id,cat_id
FROM tests
GROUP BY user_id,cat_id
) t2
ON t1.user_id = t2.user_id
AND t1.cat_id = t2.cat_id
AND t1.time = t2.MaxTime
order by t1.time desc
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.