窗口函数在SQL执行顺序中位于GROUP BY和HAVING之后、SELECT非窗口部分完成后,但早于外层ORDER BY和LIMIT;不能用于WHERE因阶段未到,需子查询或QUALIFY;PARTITION BY先切分再各分区ORDER BY;帧子句须配合ORDER BY;ORDER BY仅影响窗口内计算逻辑而非最终输出顺序;窗口函数基于完整中间结果集,不受LIMIT影响。

窗口函数不是“写在哪就执行到哪”,它在 SQL 逻辑执行链里有固定位置:一定在 GROUP BY 和 HAVING 之后、SELECT(非窗口部分)刚完成时运行,但早于外层 ORDER BY 和 LIMIT。
窗口函数为什么不能用在 WHERE 里
因为 WHERE 执行时,窗口函数根本还没算——数据连分组都还没做,更别说给每行打排名或算累计值了。你写 WHERE ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY ts DESC) = 1,数据库直接报错 column "row_number" does not exist,不是语法错,是阶段错。
-
WHERE只能访问原始表字段或 JOIN 后的列,看不到任何OVER()计算结果 - 想按窗口结果过滤,必须用子查询或 CTE 套一层,让窗口先算完再进
WHERE - 某些引擎(如 BigQuery、Snowflake)支持
QUALIFY,本质就是语法糖,帮你自动套了这层
PARTITION BY 和 ORDER BY 的生效顺序不可颠倒
PARTITION BY 是物理切分动作,ORDER BY 是每个分区内部的排序逻辑。引擎不会先全局排好序再分区,而是先按 PARTITION BY dept 拆成多个子集,再对每个子集单独跑 ORDER BY salary DESC。
- 漏写
PARTITION BY时,ORDER BY作用域是整张结果集,ROW_NUMBER()从 1 排到 N - 写了
PARTITION BY class却没写ORDER BY,ROW_NUMBER()分区内序号完全不可控(依赖页存储顺序,多次执行可能不同) - 帧子句(如
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)必须搭配ORDER BY,否则行为未定义
ORDER BY 在 OVER() 里到底管什么
它不控制最终输出顺序,只决定窗口函数计算时“当前行在哪、前后有哪些行”。比如 SUM(sales) OVER (ORDER BY date) 的默认帧是 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,没有 ORDER BY 就没法知道“preceding”是谁。
-
ROW_NUMBER()、RANK()等排名函数必须有ORDER BY,否则语法错误 -
AVG() OVER (ORDER BY x)和AVG() OVER ()结果完全不同:前者是累积平均,后者是全分区平均 - 外层
ORDER BY只影响最终展示顺序,改不了窗口内计算逻辑——想让每个班级 top1 按总分再排,得在外层再套ORDER BY total_score DESC
最容易被忽略的是:窗口函数基于的是未被 LIMIT 截断的完整中间结果集。哪怕你最后只 LIMIT 10,ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) 依然会为所有匹配行编号,而不是只编前 10 行。这点在分页取每组最新记录时尤其关键——别指望 LIMIT 能帮窗口“省算力”。

















