加 OVER 才是窗口函数,SUM(col) 不加会报错;OVER() 保留明细行并计算全表聚合,PARTITION BY 实现分组不丢行,ORDER BY 则变为累积计算。

直接用 OVER() 就行,不用 GROUP BY 也能做聚合,而且还能保留原始明细行。
为什么不能直接写 SUM(col) 而不加 OVER?
SQL 引擎会报错:ERROR: column "xxx" must appear in the GROUP BY clause or be used in an aggregate function。因为没 OVER 的 SUM 是传统聚合函数,必须配 GROUP BY 才合法;加了 OVER 才变成窗口函数,语义完全不同。
-
SUM(amount)→ 要求整条查询只返回一行(除非有GROUP BY) -
SUM(amount) OVER()→ 每行都返回全表总和,原始行一条不少 - 漏写
OVER是新手最常踩的语法错误,报错信息里其实已经提示了关键线索
OVER(PARTITION BY ...) 怎么分组又不丢明细?
这是最常用场景:按某列(比如 category)“逻辑分组”,但每行仍展示自己的 id、name、amount 等原始字段,同时新增一列显示该分类的汇总值。
-
SUM(amount) OVER(PARTITION BY category)→ 每行显示自己所属category的小计 - 支持多个字段:
PARTITION BY category, region -
PARTITION BY里不能用表达式或别名,只能是原始列名或确定性函数(如DATE(year_month)) - 如果分区字段含
NULL,所有NULL值会被归为同一组——这点容易被忽略,查不出数据时先检查NULL分布
OVER() + ORDER BY 会改变行为,慎用
在聚合类窗口函数(SUM、AVG、COUNT)中加 ORDER BY,会让结果变成累积计算,不是静态分组值。
-
SUM(amount) OVER(PARTITION BY category ORDER BY create_time)→ 每行显示“该 category 内、时间 - 不加
ORDER BY才是真正的“小计”;加了就变“滚动和”,两者语义不同,不能混用 - 如果真要静态小计,
ORDER BY必须删掉;否则即使写了PARTITION BY,结果也和预期不符 - 性能上,带
ORDER BY的窗口函数在大数据量时开销显著上升,尤其是未建索引的排序字段
MySQL 8.0+ 和旧版本的兼容差异
窗口函数在 MySQL 中是 8.0 才正式支持,低版本会直接报错 FUNCTION xxx does not exist 或语法错误。
- 确认版本:
SELECT VERSION(); - 替代方案(仅限旧版):
(SELECT SUM(amount) FROM t2 WHERE category = t1.category)—— 相关子查询,但性能差、不能用索引优化 - 变量法(如
@sum := @sum + amount)不可靠:执行顺序不保证,多线程或优化器重排后结果可能错乱,生产环境禁用 - PostgreSQL / SQL Server / Oracle 均原生支持,语法一致,无需额外适配
真正难的不是写对 OVER,而是想清楚你要的是“静态分组值”还是“动态累积值”——这两个只差一个 ORDER BY,但语义天差地别,调试时得盯住这一行括号里的内容。

















