我具有以下数据结构(简化):
Users:
ID
Name
Events:
ID
Date
Results:
ID
User ID (foreign key)
Event ID (foreign key)
Points: (int)
我想知道(最有效的方法):
我可以通过以下方式获得排行榜:
select users.name, SUM(results.points) as points
from results
inner join users on results.user_id = users.id
group by users.id
order by points DESC
但是,我想知道用户的位置,而不必尽可能返回整个表格。
编辑:我提供了一些示例数据here。
理想的输出:
| User ID | Rank |
| 3 | 1 |
| 1 | 2 |
| 2 | 3 |
和类似的东西(不是完全一样,它很灵活,只是显示每个事件的用户排名)
| User ID | After Event | Rank |
| 1 | 1 | 1 |
| 1 | 2 | 1 |
| 1 | 3 | 2 |
| 2 | 1 | 2 |
| 2 | 2 | 2 |
| 2 | 3 | 1 |
| 3 | 1 | 3 |
| 3 | 2 | 3 |
| 3 | 3 | 3 |
答案 0 :(得分:2)
MySQL 8.0+支持window functions,因此可以方便地使用dense_rank()
。
MySQL在8.0解决方案下
由于您的版本是5.7,因此您可以像下面这样模仿:
select
t.id,
CASE WHEN @prevRank = points THEN @currRank
WHEN @prevRank := points THEN @currRank := @currRank + 1
END AS rank
from (
select users.id, SUM(results.points) as points
from results
inner join users on results.user_id = users.id
group by users.id
order by points DESC
) t
cross join (SELECT @currRank := 0, @prevRank := NULL) r
如果您需要特定user
的数据,请添加一个WHERE
条件以过滤外部查询中的其他所有人:
select *
from (
<< above query here >>
) t
where id = ? -- your id here
MySQL 8.0+解决方案
rank
是保留关键字,因此在命名列时需要反引号。我们正在使用dense_rank
窗口函数,该函数将基于获得的点的od降序分配等级:
select id, dense_rank() over (order by points desc) as `rank`
from (
select users.id, SUM(results.points) as points
from results
inner join users on results.user_id = users.id
group by users.id
) t
order by `rank`
答案 1 :(得分:0)
SET @rowno = 0;
select UserID, max(points), @rowno:=@rowno+1 as rank from
(
select users.id as UserID ,users.name as users_name,events.name, SUM(results.points) as points
from results
inner join users on results.user_id = users.id
inner join events on results.event_id= events.id
group by users.id,events.name,users.name
order by points DESC
) as T
group by UserID
order by max(points) desc