sql 中 row_number over partition by 用法_sql 中 row_number 分区编号详解

sql 中 row_number over partition by 用法_sql 中 row_number 分区编号详解
最新回答
眼眸熏染离情丶

2026-10-23 07:38:22

ROW_NUMBER() OVER (PARTITION BY ...) 是 SQL 中用于在分组内生成唯一序号的窗口函数,核心作用是在指定的分区(分组)内,为每一行数据生成一个从 1 开始递增的唯一序号。

  • ROW_NUMBER():生成行号,序号从 1 开始,在每个分区内连续递增。
  • OVER():标识这是一个窗口函数,定义函数的作用范围。
  • PARTITION BY:按指定字段分组,类似 GROUP BY,但不会合并行,每个分区独立编号。
  • ORDER BY:定义组内排序方式,决定编号的顺序(默认升序 ASC,可指定降序 DESC)。

语法结构解析

  • ROW_NUMBER():生成行号。
  • OVER():表示这是一个窗口函数。
  • PARTITION BY column_name:按照某个字段进行分组,类似 GROUP BY,但不会合并行。
  • ORDER BY column_name:在每个分区内按什么顺序编号。

示例

示例 1:按销售人员分组排名

假设有一张销售记录表 sales,想查看每个销售人员按销售额从高到低的排名:

SELECT salesperson, sale_date, amount, ROW_NUMBER() OVER (PARTITION BY salesperson ORDER BY amount DESC) AS rankFROM sales;

解释:

  • 按 salesperson 分组。
  • 每组内部按 amount 降序排序。
  • 为每条记录生成从 1 开始的编号,表示排名。

示例 2:分组排名(员工每月业绩)

查看每位员工每月的业绩排名:

ROW_NUMBER() OVER (PARTITION BY employee_id, month ORDER BY performance_score DESC)

解释:

  • 按 employee_id 和 month 分组。
  • 每组内部按 performance_score 降序排序。
  • 生成排名编号,显示每个人每个月的业绩排名。
示例 3:去重(保留每个用户最新日志)

假设 user_logs 表中有重复的用户记录,想只取每个用户最新的一条:

WITH ranked_data AS ( SELECT user_id, log_time, action, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY log_time DESC) AS rn FROM user_logs)SELECT * FROM ranked_data WHERE rn = 1;

解释:

  • 按 user_id 分组。
  • 每组内部按 log_time 降序排序。
  • 生成编号 rn,取 rn = 1 的记录,即每个用户最近的一条日志。

常见使用场景

  • 分组排名:如按销售人员分组后按销售额排序。
  • 去重:如保留每个用户最新或最旧的一条记录。
  • 筛选:如筛选每个分组中的前 N 条记录。

使用时需要注意的细节

  • 分区字段要选对:PARTITION BY 后面的字段决定了分组方式,漏掉关键字段会导致结果错误。
  • 排序方式影响编号顺序:默认升序 ASC(从小到大),可指定降序 DESC(从大到小),根据业务需求选择。
  • 编号唯一且连续:ROW_NUMBER() 生成的编号在每个分区内严格从 1 开始递增,不会有重复值,这点与 RANK() 和 DENSE_RANK() 不同。

总结

ROW_NUMBER() OVER (PARTITION BY ...) 是一个实用的窗口函数,特别适合做排名、去重、筛选等操作。使用时需明确:

  • 如何分组(PARTITION BY)。
  • 如何排序(ORDER BY)。

掌握这些后,就能灵活运用该函数解决实际问题。多练习几次,对分区字段和排序方向的选择会更加熟练。