SQL ROW_NUMBER、RANK 和 DENSE_RANK 有什么区别?
面试怎么回答
ROW_NUMBER 给每行唯一序号,同值也不并列;RANK 同值并列,但并列后会跳号;DENSE_RANK 同值并列且不跳号。每组严格取 N 行时我会用 ROW_NUMBER,并补充唯一排序字段保证结果稳定;如果业务要求保留并列名次,再根据是否跳号选择 RANK 或 DENSE_RANK。关键不是记函数,而是先确认“前 N 行”还是“前 N 个名次”。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
四个人的分数分别是:
100、100、90、80
同样按分数降序,三种窗口函数却会得到三组不同排名:
ROW_NUMBER : 1、2、3、4
RANK : 1、1、3、4
DENSE_RANK : 1、1、2、3

差异只取决于两个问题:并列值是否使用同一名次,以及并列之后是否跳号。
ROW_NUMBER:每一行都有唯一序号
即使排序值相同,ROW_NUMBER() 也会给每一行分配不同序号。
ROW_NUMBER() OVER (
PARTITION BY class_id
ORDER BY score DESC, student_id
)
如果排序字段存在并列,又没有补充稳定的唯一字段,同分记录谁是 1、谁是 2 可能不稳定。
因此 ROW_NUMBER 很适合:
- 每组只保留一条记录
- 按明确规则取最新一条
- 严格限制每组返回 N 行
RANK:并列同名次,后续跳号
两个 100 分都是第 1 名,占用了前两个位置,下一名直接是第 3 名。
它符合竞赛排名语义,适合表达“并列第一,下一位第三”。
DENSE_RANK:并列同名次,后续不跳号
两个 100 分都是第 1 名,90 分仍然是第 2 名。
它更像对不同排序值进行连续编号,常用于价格档位、分数层级或连续等级。

做 Top N 时怎么选?
每组严格返回 N 行
用 ROW_NUMBER <= N,但要补充稳定排序字段,明确同分时谁优先。
并列第 N 名都要保留
根据业务排名语义选择 RANK <= N 或 DENSE_RANK <= N。
注意:一旦保留并列,返回行数可能超过 N。RANK 按位置排名并会跳号,DENSE_RANK 按不同值排名且不跳号,两者的结果范围也可能不同。
一个典型错误
需求说“每个部门取工资最高的 3 个人”,SQL 却写:
RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) <= 3
如果第 3 名有多人并列,结果就会超过 3 行。
这不一定是 SQL 错,而是需求没有说清楚:要“严格 3 个人”,还是“前 3 个名次”。
前者应该用 ROW_NUMBER 并定义并列规则;后者才允许保留同名次记录。
排名函数的选择,本质上是业务如何定义并列。