在MySQL 8.0及以上版本中,窗口函数为我们实现榜单排名提供了非常简洁的方案。通过专用的排名函数,我们可以直接在查询中计算出每个用户的名次,而不再依赖复杂的子查询或用户变量。

常用的排名函数
MySQL主要提供以下三个窗口函数来处理排名,它们的核心差异在于对并列成绩的处理方式:
- ROW_NUMBER():不考虑并列,每一行分配一个唯一的连续序号。
- RANK():相同成绩并列,并列后跳过后面的名次。
- DENSE_RANK():相同成绩并列,但并列后不跳过名次。
准备示例数据
假设我们有一张用户积分表 user_score,结构如下:
| id | user_name | score |
|---|---|---|
| 1 | 张三 | 100 |
| 2 | 李四 | 100 |
| 3 | 王五 | 90 |
| 4 | 赵六 | 80 |
实现不同规则的榜单排名
使用 ROW_NUMBER 生成唯一排名
下面的查询会按分数从高到低给每个人一个不重复的顺序号:
SELECT user_name, score, ROW_NUMBER() OVER (ORDER BY score DESC) AS rank_num FROM user_score;
使用 RANK 处理并列并跳号
张三和李四同分,都会排第1,王五则排第3:
SELECT user_name, score, RANK() OVER (ORDER BY score DESC) AS rank_val FROM user_score;
使用 DENSE_RANK 处理并列不跳号
同样两人并列第1,王五会紧接排第2:
SELECT user_name, score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank_val FROM user_score;
按分组做榜单排名
如果要在不同部门内分别排名,可以加上 PARTITION BY 子句:
SELECT dept_id, user_name, score, DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY score DESC) AS dept_rank FROM user_score;
总结
使用MySQL窗口函数实现榜单排名,代码直观且易于维护。实际开发中,应根据业务对并列名次的要求,在 ROW_NUMBER、RANK 与 DENSE_RANK 之间选择合适的函数,必要时结合 PARTITION BY 完成分组榜单。