ROW_NUMBER() 必须配合 OVER 子句使用,否则报语法错误;正确用法为 OVER (ORDER BY ...) 或 OVER (PARTITION BY ... ORDER BY ...);其结果为计算列,不可在 WHERE 中直接引用。

ROW_NUMBER() 必须配合 OVER 子句,否则会报错
直接写 SELECT ROW_NUMBER() 不带 OVER 会触发语法错误,比如 PostgreSQL 报 ERROR: window function row_number requires an OVER clause,SQL Server 也类似。窗口函数不能脱离上下文独立存在。
正确写法必须明确排序逻辑和(可选)分组逻辑:
-
OVER (ORDER BY score DESC):全表排序编号,适用于全局 Top N -
OVER (PARTITION BY category ORDER BY score DESC):先按category分组,组内再按score降序编号,这才是分组 Top N 的基础
分组 Top N 要用子查询或 CTE 过滤 row_num ≤ N
ROW_NUMBER() 是计算列,不能在 WHERE 中直接引用——因为 WHERE 执行顺序早于窗口函数计算。常见错误是写 WHERE ROW_NUMBER() OVER (...) ,这在所有主流 SQL 引擎中都会报错。
必须把窗口函数结果放到子查询或 CTE 中,再在外层过滤:
PARTITION BY
- 用
ROW_NUMBER()取 Top 3,即使有并列,也只返回恰好 3 行(可能“挤掉”另一个同分项) - 用
RANK()取 Top 3,可能返回 4 行甚至更多(只要第 3 名有并列) - 业务上要求“分数前 3 名,同分全进”,就得换
RANK(),不能硬套ROW_NUMBER()
性能敏感场景要检查执行计划是否走索引
PARTITION BY + ORDER BY 组合对索引很敏感。例如 PARTITION BY dept_id ORDER BY salary DESC,理想索引是 (dept_id, salary)(B-tree 索引,前导列匹配分区键)。
没合适索引时,数据库可能触发临时文件排序,尤其在大数据量分组下,ROW_NUMBER() 会明显变慢。可加 EXPLAIN 或 EXPLAIN ANALYZE 确认是否出现 WindowAgg 节点伴随 Sort 且 Buffers 消耗高。
小技巧:如果只查单个分组(如 WHERE dept_id = 'ENG'),可以去掉 PARTITION BY,改用 ORDER BY + LIMIT,效率通常更高,也更易命中索引。
实际写分组 Top N 时,最容易被忽略的是并列处理逻辑和索引适配——前者导致业务结果偏差,后者让语句在测试环境飞快、上线后卡住。










