#1 SQL 中等

窗口函数和 GROUP BY 有什么区别?各自适用什么场景?

窗口函数聚合GROUP BY

🎯 考察意图

考察候选人对「聚合会丢行」与「窗口保留行」这两种范式的本质理解,以及能否在业务场景里选对工具。

📐 回答框架

  1. 先给一句话对比:GROUP BY 折叠行;窗口函数在保留明细的前提下做计算。
  2. 说清语法结构:OVER(PARTITION BY … ORDER BY …) 与聚合函数的分工。
  3. 举 1–2 个业务例子(排名、累计、同组对比)。
  4. 补充常见窗口类型:排名、聚合窗口、偏移(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 折叠行;窗口函数在行上「挂」上下文统计。