ROW_NUMBER() 必须配合OVER()使用,是窗口函数而非普通函数;空OVER()不保证行序稳定,生产环境须显式指定ORDER BY;PARTITION BY用于分组内编号,不聚合数据。

ROW_NUMBER() 必须配合 OVER() 使用,否则直接报错
单独写 ROW_NUMBER() 会触发类似 ERROR: window function ROW_NUMBER requires an OVER clause 的错误。它不是普通函数,而是窗口函数,语法上强制要求 OVER() 子句——哪怕你只是想按自然顺序编号。
常见误写:SELECT name, ROW_NUMBER() FROM users; → 错;正确写法必须带 OVER:
SELECT name, ROW_NUMBER() OVER() AS rn FROM users;
注意:OVER() 里为空表示“全表无分区、无排序”,但实际结果的行序由查询执行计划决定,**不保证稳定**。生产环境务必显式指定 ORDER BY。
ORDER BY 在 OVER() 里决定编号逻辑,不是 SELECT 后的 ORDER BY
很多人把 ORDER BY 写在查询末尾,以为能控制 ROW_NUMBER() 编号顺序——没用。窗口函数的排序只认 OVER(ORDER BY ...) 里的定义。
-
ROW_NUMBER() OVER(ORDER BY created_at DESC):按创建时间倒序编号,最新数据是 1 -
ROW_NUMBER() OVER(ORDER BY status, id):先按状态分组内排序,再按 ID 排 - 如果漏写
ORDER BY,不同数据库行为不一:PostgreSQL 允许空OVER()但结果不可靠;MySQL 8.0+ 要求必须有ORDER BY
示例(查每个用户最近一次订单的序号):
SELECT user_id, order_id, amount,
ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY created_at DESC) AS rn
FROM orders;
PARTITION BY 划分独立编号区间,别和 GROUP BY 混用
PARTITION BY 是 ROW_NUMBER() 实现“分组内编号”的核心,比如“每个部门内员工按薪资排名”。它不聚合数据,只是重置计数器——这点和 GROUP BY 本质不同。
典型陷阱:
- 写了
PARTITION BY dept却忘了ORDER BY salary→ 编号随机,毫无意义 - 误以为
PARTITION BY会自动去重 → 不会,原始行全保留,只是编号从 1 重新开始 - 在同一个查询里混用
GROUP BY和窗口函数时,必须确保SELECT中非聚合字段都在GROUP BY列表中,否则报错(如 PostgreSQL)
实用场景:取每个分类下销量前 3 的商品
ROW_NUMBER()










