我有一个带有该结构的'user_score'表:
|id|user_id|group_id|score| timestamp |
| 1| 1| 1| 500| 2013-02-24 18:00:00|
| 2| 2| 1| 200| 2013-02-24 18:01:50|
| 3| 1| 2| 100| 2013-02-24 18:06:00|
| 4| 1| 1| 6000| 2013-02-24 18:07:30|
我需要做的是从该表中选择来自确切组的所有用户。选择该组中的实际(根据时间戳)得分及其排名。
我所拥有的是(编辑:在Jocachin的评论之后我发现我自己的查询不能按预期工作,对所有人抱歉):
SELECT user_id, score, @curRank := @curRank + 1 AS rank
FROM (
SELECT *
FROM (
SELECT * FROM `user_score`
WHERE `group_id` = 1
ORDER BY `timestamp` DESC
) AS sub2
GROUP BY `user_id`
) AS sub, (SELECT @curRank := 0) r
ORDER BY `rank`
示例数据和group_id = 1的预期结果:
|user_id|score|rank|
| 1| 6000| 1|
| 2| 200| 2|
但是MySQL子选择有点问题,你还能看到其他解决方案吗?
我可能需要稍后获得该组中单个用户的排名。我此刻迷失了。
答案 0 :(得分:5)
虽然我不确定这个上下文中“有问题”是什么意思,但是这里的查询被重写为带有子查询的普通LEFT JOIN
,只是为了在最后得到排名(ORDER BY
需要在排名前完成;)
SELECT user_id, score, @rank := @rank + 1 AS rank FROM
(
SELECT u.user_id, u.score
FROM user_score u
LEFT JOIN user_score u2
ON u.user_id=u2.user_id
AND u.`timestamp` < u2.`timestamp`
WHERE u2.`timestamp` IS NULL
ORDER BY u.score DESC
) zz, (SELECT @rank := 0) z;
编辑:要考虑group_id,您需要稍微扩展一下查询;
SELECT user_id, score, @rank := @rank + 1 AS rank FROM
(
SELECT u.user_id, u.score
FROM user_score u
LEFT JOIN user_score u2
ON u.user_id=u2.user_id
AND u.group_id = u2.group_id -- u and u2 have the same group
AND u.`timestamp` < u2.`timestamp`
WHERE u2.`timestamp` IS NULL
AND u.group_id = 1 -- ...and that group is group 1
ORDER BY u.score DESC
) zz, (SELECT @rank := 0) z;
答案 1 :(得分:1)
SELECT user_id, score, @rank := @rank + 1 AS rank
FROM
(
SELECT
user_id AS user_id,
SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY timestamp DESC), ',', 1)
AS score
FROM user_score
WHERE group_id=1
GROUP BY user_id
) AS u,
(
SELECT @rank := 0
) AS r
ORDER BY score DESC;
答案 2 :(得分:1)
我知道答案已经发布并被接受但我对你原来的查询有一点意见,我认为值得一提。
分组时,您只能选择分组的列和具有聚合函数的列,例如MAX和COUNT。选择其他列在技术上是错误的。
这是有道理的,因为不清楚应该返回哪一行的数据。 Mysql返回group by中第一行的数据;这就是您的查询有效的原因(因为内部子查询中的时间戳顺序)。另一方面,SQL服务器引发了异常。
我认为SQL Server方法是正确的,应该避免这种类型的查询。
答案 3 :(得分:0)
我今天遇到了类似的问题,在尝试实施接受的答案失败后,我做了这么简单的查询
SELECT user_score.user_id,
MAX(user_score.score) AS score
FROM user_score
WHERE user_score.group_id = 1
GROUP BY user_score.user_id,
user_score.group_id
ORDER BY user_score.score DESC,
user_score.`timestamp` ASC