必须用窗口函数(over)而非group by的典型场景是:既要保留每条原始记录(如员工姓名、薪资),又要同时计算并展示分组统计值(如部门平均薪资、个人排名、累计销售额);移动平均、lag/lead取前后行、row_number排序编号等能力仅窗口函数支持。

需要保留原始行数据时,必须用窗口函数;只想要分组汇总结果时,聚合函数更直接、兼容性更好。
什么时候必须用 OVER() 而不能用 GROUP BY
典型场景是:既要看到单条记录(比如每个员工的姓名、部门、薪资),又要同时显示计算值(比如该部门平均薪资、个人薪资排名、累计销售额)。GROUP BY 会强制压缩行数,无法返回“张三 10000 9000”这种带明细+聚合的结果。
- 想在一行里同时展示
name、salary和AVG(salary) OVER (PARTITION BY department)→ 只能用窗口函数 - 要算移动平均(如近3天销量均值)、前后行差值(
LAG()/LEAD())、或按顺序编号(ROW_NUMBER())→ 窗口函数专属能力,聚合函数做不到 -
GROUP BY后 SELECT 中出现未分组字段,MySQL 8.0+ 默认报错Expression #1 of SELECT list is not in GROUP BY clause,而窗口函数天然规避这个问题
AVG() 作聚合函数和作窗口函数的区别
同一个函数名,行为完全不同:是否加 OVER() 是分水岭。
从 AI 编程会话日志(Clawdbot、Claude Code、Codex)中提取对话记录。该功能用于在用户要求导出提示词历史、会话日志或 `.jsonl` 格式的会话文件时使用。
- 不加
OVER():SELECT department, AVG(salary) FROM employees GROUP BY department→ 返回 2 行(假设两个部门),每行是部门级汇总 - 加
OVER():SELECT name, department, salary, AVG(salary) OVER (PARTITION BY department)→ 返回 N 行(原始多少人就多少行),每行都带本部门平均值 - 注意:
AVG()作窗口函数时,PARTITION BY不是必须项;省略它就等价于对全表计算平均值,类似AVG(salary) OVER ()
MySQL 版本与性能影响
窗口函数不是万能钥匙,它有明确的版本门槛和执行代价。
- MySQL 5.7 及更早版本不支持窗口函数,强行写
OVER()会直接报语法错误You have an error in your SQL syntax - MySQL 8.0+ 支持,但复杂
ROWS BETWEEN定义(如大范围滑动窗口)可能显著拖慢查询,尤其在未建合适索引的排序字段上 - 聚合函数在所有 MySQL 版本都可用,且优化器对
GROUP BY的路径选择更成熟;简单汇总场景下,它通常比等效的窗口写法更快、内存占用更低 - 如果只是求部门平均值,又不需要明细行,硬套
AVG() OVER (PARTITION BY dept)反而多出不必要的计算开销
真正容易被忽略的是:窗口函数的 ORDER BY 子句在 OVER() 里不是可有可无的装饰——它直接影响 RANK()、ROW_NUMBER()、SUM() OVER (ORDER BY ... ROWS) 的结果逻辑,漏写或写错顺序,得到的排名或累计值很可能完全偏离预期。










