row_number() over (partition by ...) 是 sql 中用于在分组内生成唯一序号的窗口函数。1. row_number() 生成行号;2. over() 标识窗口函数范围;3. partition by 按指定字段分组,类似 group by 但不合并行;4. order by 定义组内排序方式。常见用途包括分组排名(如按销售人员分组后按销售额排序)、去重(如保留每个用户最新日志)。使用时需注意正确选择分区字段和排序方向,编号始终唯一且连续,适用于筛选、排名等场景。

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

比如你有一张销售记录表,想看看每个销售人员按销售额从高到低的排名,这时候就可以用它来编号。
如何理解 ROW_NUMBER() OVER (PARTITION BY ...)
这个语法结构分为几个部分:

-
ROW_NUMBER():生成行号。 -
OVER():表示这是一个窗口函数。 -
PARTITION BY column_name:按照某个字段进行分组,类似GROUP BY,但不会合并行。 -
ORDER BY column_name:在每个分区内按什么顺序编号。
举个例子:
SELECT
salesperson,
sale_date,
amount,
ROW_NUMBER() OVER (PARTITION BY salesperson ORDER BY amount DESC) AS rank
FROM sales;这段 SQL 的意思是:按销售人员分组,每组内部按销售额从高到低排序,并给每条记录打上编号。

常见使用场景
分组排名
最常见的用途就是做排名。比如你要看每位员工每月的业绩排名,就可以这样写:
ROW_NUMBER() OVER (PARTITION BY employee_id, month ORDER BY performance_score DESC)
这样就能看到每个人每个月的排名情况。
去重保留最新或最旧的一条
有时候你会遇到重复数据,比如同一用户有多条记录,你想只取最新的那一条。可以用 ROW_NUMBER() 配合子查询实现:
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;这里的意思是:每个用户按时间倒序排,取第一条数据,也就是最近的一条日志。
使用时需要注意的细节
-
分区字段要选对:
PARTITION BY后面的字段决定了你怎么分组。如果漏了关键字段,结果可能完全不对。 -
排序方式影响编号顺序:默认升序排,
ASC是从小到大,DESC是从大到小。根据业务需要选择合适的排序方式。 -
编号不唯一:虽然叫
ROW_NUMBER(),但其实它是严格按排序生成的连续整数,不会有重复值,这点和RANK()、DENSE_RANK()不一样。
总结一下
ROW_NUMBER() OVER (PARTITION BY ...) 就是用来在分组内编号的工具,特别适合做排名、去重、筛选等操作。只要搞清楚怎么分组、怎么排序,基本就能用好了。
基本上就这些,不复杂但容易忽略的地方在于分区字段和排序方向的选择,多练几次就熟悉了。










