窗口函数在保留每行数据基础上叠加计算结果,而普通聚合函数通过group by压缩行;over子句中partition by、order by、rows/range可部分省略但影响逻辑;典型易错点包括混淆排名函数、误用lag/lead、where中引用窗口别名报错。

窗口函数是SQL进阶查询的核心能力,面试中常考其逻辑理解、执行顺序和实际场景应用,不是简单背语法就能应付的。
窗口函数和普通聚合函数的区别在哪?
关键在于是否“打散行”:普通GROUP BY会压缩多行成一行,丢失原始行细节;窗口函数则在保留每行数据的基础上,叠加计算结果(如当前行的累计值、排名、前后行差值等)。
典型对比:
- AVG(salary) FROM emp GROUP BY dept → 每部门只返回1行平均工资
- AVG(salary) OVER(PARTITION BY dept) → 每员工行都附带其所在部门的平均工资,共N行输出
OVER()子句三要素必须写全吗?
不必须,但缺一不可地影响结果逻辑:
pui 是一款基于jQyery开发的插件库。目前线上稳定使用已有2年多,丰富的接口,简单明了的调用方式,灵活的回调函数,让您轻轻松松打造出富有灵活交互的Web前端界面解决方案。 插件库封装了布局、表单元素、表单校验、弹窗、toast、气泡pop、tab切换、日历时间、分页、表格、树、css命名等功能
- PARTITION BY:可省略,默认全表为一个分区(类似没分组)
- ORDER BY:对多数函数非必需,但对ROW_NUMBER()、RANK()、SUM() OVER(... ORDER BY ...)等排序敏感函数必须存在,否则报错或结果无意义
- ROWS/RANGE BETWEEN:可省略,此时默认行为依函数而定(如SUM() OVER(ORDER BY t)默认等价于ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
常见的易错点和调试技巧
面试时写错往往不是语法,而是逻辑断层:
- 混淆RANK()、DENSE_RANK()、ROW_NUMBER()的并列处理方式——用相同ORDER BY字段查3个函数并排对比,一眼看出差异
- 误以为LAG(col, 1)能取到“下一行”,其实它是取“上一行”,LEAD()才是向下偏移
- 在WHERE中直接引用窗口函数别名会报错(如WHERE rn = 1),因为窗口函数在WHERE之后执行——需套一层子查询或CTE再过滤
- 多个窗口函数共用同一OVER子句时,可提取为WINDOW w AS (PARTITION BY x ORDER BY y),提升可读性(部分数据库支持,如PostgreSQL、MySQL 8.0+)
一道典型综合题思路拆解
题目:查每个部门薪资第2高的员工(允许并列,取所有第2高者)
解法要点:
- 先用DENSE_RANK() OVER(PARTITION BY dept ORDER BY salary DESC)生成部门内连续排名
- 注意不能用ROW_NUMBER()——它会把同薪员工排成不同名次,破坏“第2高”的语义
- 外层WHERE筛选rank = 2,即可拿到全部符合条件的记录









