窗口函数和 GROUP BY 有什么区别?各自适用什么场景?
窗口函数聚合GROUP BY
考察意图
考察候选人对「聚合会丢行」与「窗口保留行」这两种范式的本质理解,以及能否在业务场景里选对工具。
回答框架
- 先给一句话对比:GROUP BY 折叠行;窗口函数在保留明细的前提下做计算。
- 说清语法结构:OVER(PARTITION BY … ORDER BY …) 与聚合函数的分工。
- 举 1–2 个业务例子(排名、累计、同组对比)。
- 补充常见窗口类型:排名、聚合窗口、偏移(LAG/LEAD)。
参考答案(口述版)
一句话:GROUP BY 会把多行「折叠」成更少的组;窗口函数在「不丢行」的前提下,对每一行按窗口范围做计算。
GROUP BY 适合「只要汇总结果」:例如每个城市的 GMV、每个用户的订单数。结果集行数通常远小于原表。
窗口函数适合「既要明细又要上下文统计」:例如给每笔订单标上该用户的累计消费、同城排名、相对上一日的差值。语法核心是 函数() OVER (PARTITION BY … ORDER BY … [ROWS/RANGE …])。
常见三类:
1. 排名:ROW_NUMBER / RANK / DENSE_RANK
2. 聚合窗口:SUM/AVG/COUNT() OVER(...)
3. 偏移:LAG / LEAD 做环比、漏斗前后步
面试时可主动对比:若业务最终只要汇总,GROUP BY 更清晰且优化器更好推;若下游还要明细字段或需要「同组对比」,窗口函数更合适。
关键词
不丢行OVERPARTITION BY排名函数LAG/LEAD
面试官可能的追问
追问 1:ROW_NUMBER、RANK、DENSE_RANK 的区别?
ROW_NUMBER 严格唯一序号,并列也强制拆开;RANK 并列同名次并跳号(1,1,3);DENSE_RANK 并列同名次但不跳号(1,1,2)。取 TopN 不重复用 ROW_NUMBER;要「并列并列算并列」用 RANK/DENSE_RANK。
追问 2:窗口函数能替代所有 GROUP BY 吗?
不能优雅替代。窗口结果仍是明细粒度,若最终要一行一组,还得再 DISTINCT/再聚合,既难读又可能更慢。该折叠就折叠。
常见踩坑
- 把窗口函数当成 GROUP BY 用,忘了结果仍是一行一条明细
- ORDER BY 写错导致累计/排名语义完全反了
- PARTITION BY 漏字段,把全局排名当成组内排名
记忆锚点
GROUP BY 折叠行;窗口函数在行上「挂」上下文统计。