全局编号(不分组)
ROW_NUMBER() 是 SQL 中一个非常重要的窗口函数(Window Function),用于为查询结果集中的每一行生成唯一的、连续的整数序号(从 1 开始)。
ROW_NUMBER()OVER([PARTITIONBY分组字段]ORDERBY排序字段[ASC|DESC])| 特性 | 说明 |
|---|---|
| 唯一性 | 每一行都有唯一的行号,即使排序字段值相同 |
| 连续性 | 行号是 1, 2, 3, … 连续递增 |
| 依赖排序 | 行号顺序由ORDER BY决定 |
| 支持分组 | 用PARTITION BY可在每个分组内重新从 1 开始编号 |
注意:ROW_NUMBER() 只影响行号生成逻辑,不改变最终结果集的物理顺序。
如果你想让查询结果也按某个顺序显示,仍需在主查询中加 ORDER BY
SELECTname,salary,ROW_NUMBER()OVER(ORDERBYsalaryDESCNULLSLAST)ASrnFROMemployees;NULLS LAST 表示如果salary 字段为null 就放在最后
对比 RANK()或 DENSE_RANK():它们会在相同值时产生并列排名(如两个第2名),但 ROW_NUMBER()永远不重复分组编号(按部门排名)
SELECTdept_id,name,salary,ROW_NUMBER()OVER(PARTITIONBYdept_idORDERBYsalaryDESC)ASdept_rankFROMemployees;| dept_id | name | salary | dept_rank |
|---|---|---|---|
| 1 | Alice | 9000 | 1 |
| 1 | Bob | 8000 | 2 |
| 2 | Carol | 8500 | 1 |
| 2 | Dave | 7000 | 2 |
获取每组前 N 条记录(经典用法)
-- 获取每个部门薪资最高的 1 人WITHRankedEmpAS(SELECTdept_id,name,salary,ROW_NUMBER()OVER(PARTITIONBYdept_idORDERBYsalaryDESC)ASrnFROMemployees)SELECTdept_id,name,salaryFROMRankedEmpWHERErn=1;这是 SQL 中实现“Top-N per Group”最常用的方法。
WITH … AS
这里 AS 后面是查询语句作为一个结果(可以当做一个表) 给后面的SELECT使用
RANK() / DENSE_RANK()
| 函数 | 相同值处理 | 示例(值:100, 100, 90) |
|---|---|---|
ROW_NUMBER() | 强制唯一 | 1, 2, 3 |
RANK() | 并列,跳过后续 | 1, 1, 3 |
DENSE_RANK() | 并列,不跳过 | 1, 1, 2 |