dense_rank生成连续排名是因为相同排序值获相同名次且后续名次紧接上一个已用数字,如两个第1名后直接为第2名;而rank遇重复会跳过名次,row_number则强行递增编号。

为什么DENSE_RANK生成的是连续排名
DENSE_RANK() 的设计目标就是跳过重复值但不产生空档——比如两个并列第1名后,下一个一定是第2名,而不是第3名。它不像 RANK() 那样留空位,也不像 ROW_NUMBER() 那样强行编号。核心机制是:相同排序值获得相同排名,后续排名紧接上一个已用数字。
DENSE_RANK和RANK的区别在哪
两者都对相同排序键返回相同排名,但后续处理不同:
-
RANK():遇到重复后跳过对应数量的名次(如两个第1名 → 下一个是第3名) -
DENSE_RANK():重复后只占一个名次位置(如两个第1名 → 下一个是第2名)
示例数据:score = [95, 95, 87, 87, 80]
score | RANK() | DENSE_RANK() 95 | 1 | 1 95 | 1 | 1 87 | 3 | 2 87 | 3 | 2 80 | 5 | 3
ORDER BY必须明确,否则结果不可靠
DENSE_RANK() 必须配合 ORDER BY 子句使用,且该子句必须写在 OVER() 内部。漏写或写错顺序会导致语法错误或逻辑错乱。
- ✅ 正确:
DENSE_RANK() OVER (ORDER BY score DESC) - ❌ 错误:
DENSE_RANK() OVER ()(多数数据库报错) - ⚠️ 危险:
DENSE_RANK() OVER (ORDER BY score)但业务要求降序排名——结果完全反向
分区(PARTITION BY)下连续排名仍保持局部连续
加 PARTITION BY 后,DENSE_RANK() 在每个分组内独立计数,每组都从1开始,且组内依然连续。
例如按 department 分组排名工资:
SELECT name, department, salary, DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank FROM employees;
这时销售部的“第2名”和市场部的“第2名”互不影响,各自组内无空档。注意:跨分区不连续是正常行为,不是 bug。
真正容易被忽略的是——当多个字段参与排序时,ORDER BY 中字段顺序和方向(ASC/DESC)会显著影响重复判定边界。比如 ORDER BY dept ASC, salary DESC 下,并列只发生在部门和薪资都相同时,稍有差异就断开连续性。










