← 返回题目列表

ROW_NUMBER、RANK 和 DENSE_RANK 有什么区别?

中等 第 19 / 28 题 更新于 2026/07/29
SQL窗口函数排名ROW_NUMBER

简化版

ROW_NUMBER 给每行生成唯一序号,即使排序值相同也会继续编号;RANK 遇到并列名次会跳号;DENSE_RANK 遇到并列名次不跳号。比如分数 100、90、90、80,ROW_NUMBER 是 1、2、3、4,RANK 是 1、2、2、4,DENSE_RANK 是 1、2、2、3。

详细版

这三个函数都属于排名窗口函数,常用于 Top N、去重取最新、排行榜、分组排序。它们都需要 OVER (PARTITION BY ... ORDER BY ...) 定义分组和排序。

选择时看业务语义:取每组唯一一条记录用 ROW_NUMBER;排行榜允许并列且名次跳号用 RANK;想要连续名次用 DENSE_RANK。如果排序字段不唯一,ROW_NUMBER 的结果可能不稳定,需要补充唯一排序字段。

面试中最好给具体例子,否则三个函数很容易讲混。

完整版教学

一、共同点

三者都是窗口函数。

都不会像 GROUP BY 那样合并行。

都依赖窗口内排序。

都可以按部门、用户、类目等分区排名。

排名结果通常再被外层查询过滤。

二、基础示例

SELECT
  name,
  score,
  ROW_NUMBER() OVER (ORDER BY score DESC) AS rn,
  RANK() OVER (ORDER BY score DESC) AS rnk,
  DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rnk
FROM exam_scores;

如果分数相同,RANKDENSE_RANK 会给相同名次。

ROW_NUMBER 仍然会给不同序号。

三、结果对比

分数ROW_NUMBERRANKDENSE_RANK
100111
90222
90322
80443

这个表是面试里最清晰的解释方式。

四、典型使用场景

ROW_NUMBER 常用于每组取最新一条。

RANK 常用于真实竞赛排名。

DENSE_RANK 常用于连续档位排名。

如果要求“每个部门薪资前三名,包含并列”,通常用 DENSE_RANKRANK

如果要求“每个部门只取三行”,通常用 ROW_NUMBER

五、每组取最新记录

WITH t AS (
  SELECT
    *,
    ROW_NUMBER() OVER (
      PARTITION BY user_id
      ORDER BY created_at DESC, id DESC
    ) AS rn
  FROM user_events
)
SELECT *
FROM t
WHERE rn = 1;

这里加 id DESC 是为了保证同一时间下排序稳定。

六、并列名次的业务含义

排行榜要提前确认是否允许并列。

并列后是否跳号也要确认。

不同产品对“前三名”的定义不同。

如果第三名并列多人,结果可能超过三行。

排名函数选择不是语法偏好,而是业务规则选择。

七、误区和追问

  • 误区:三个函数只是名字不同。 它们对并列排序值的处理完全不同。
  • 误区:ROW_NUMBER 排序值相同也稳定。 如果 ORDER BY 不唯一,数据库可以用不同顺序返回并列行。
  • 误区:取前三名一定返回三行。 使用 RANKDENSE_RANK 时,并列可能返回超过三行。
  • 追问:每组去重保留最新用哪个? 通常用 ROW_NUMBER,并补充唯一排序字段。
  • 追问:比赛排名用哪个? 常用 RANK,因为并列后会跳号。
  • 追问:薪资前三档用哪个? 常用 DENSE_RANK,因为关注不同薪资档位。

八、面试收束

用一个分数例子解释差异。

再结合去重、排行榜和 Top N 场景说明选择依据。

最后提醒排序稳定性。