MySQL,获取用户排名

11

我有一个类似下面的MySQL表:

id     name     points
1      john     4635
3      tom      7364
4      bob      234
6      harry    9857

我想要获取单个用户的排名,而不需要选择所有用户。 我只想通过id选择单个用户并获取其由积分确定的排名。

例如,通过id 3选择并返回排名为2的tom。

谢谢

Eef

3个回答

19
SELECT  uo.*, 
        (
        SELECT  COUNT(*)
        FROM    users ui
        WHERE   (ui.points, ui.id) >= (uo.points, uo.id)
        ) AS rank
FROM    users uo
WHERE   id = @id

密集排名:

SELECT  uo.*, 
        (
        SELECT  COUNT(DISTINCT ui.points)
        FROM    users ui
        WHERE   ui.points >= uo.points
        ) AS rank
FROM    users uo
WHERE   id = @id

2
@Barmar:如果存在并列情况,这将使用“id”作为次要标准。 - Quassnoi
1
@Barmar:要模拟DENSE_RANK(这就是你所谈论的),只需将COUNT(*)替换为COUNT(DISTINCT points)即可。 - Quassnoi
1
那也将会把你前面的名次合并。如果分数是10、9、9、8、8,则排名应该是1、2、2、4、4(或更具体地说,是1、2-3、2-3、4-5、4-5)。 - Barmar
1
@Barmar:排名有三个窗口函数:ROW_NUMBER(我的原始查询),RANK(你之前的评论)和DENSE_RANK(我的之前的评论)。由于它们都存在并被使用,我不会在不知道OP的确切意图的情况下使用“应该”。 - Quassnoi
1
我认为游戏排名通常报告的方式是我描述的方式。他们会报告类似“并列第四和第五名”的内容。如果第一名有平局,那么紧随其后的玩家将获得第三名,而不是第二名。 - Barmar
显示剩余4条评论

2

@Quassnoi的解决方案在出现平局时会失败。以下是可以解决平局问题的解决方案:

SELECT *,
IF (@score=ui.points, @rank:=@rank, @rank:=@rank+1) rank,
@score:=ui.points score
FROM users ui,
(SELECT @score:=0, @rank:=0) r
ORDER BY points DESC

请注意,如果第一名得分为0,则排名将为0。此外,在出现并列的情况下,排名会递增,而不是跳过,例如10-第1名,9-第2名,9-第2名,6-第3名。此外,获取行应该在子查询中进行,因为排序是在排名之后应用的。 - Sean

0
 SET @rownum := 0;
 SELECT rank, score FROM ( SELECT @rownum := @rownum +1 AS rank, `score` ,`user_id`
 FROM leaderboard 
 ORDER BY  `score` DESC , `updated_timestamp` ) as result WHERE `user_id`=$user_id
 LIMIT 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接