SUM() 是聚合函数,必须配合 GROUP BY 使用或单独使用;若 SELECT 中含非聚合字段(如 region)和 SUM(sales),则必须将 region 列入 GROUP BY,否则报错。

GROUP BY 必须和 SUM 配合使用,否则报错
直接写 SUM(sales) 不加 GROUP BY,MySQL 会报 ERROR 1140: In aggregated query without GROUP BY;PostgreSQL 更严格,直接拒绝执行。这是因为 SUM() 是聚合函数,它需要明确“按什么分组来汇总”,不能和未分组的普通列混用。
常见错误写法:SELECT region, SUM(sales) FROM orders; —— 这在多数数据库里会失败,因为 region 没有参与分组,也没被聚合。
- 正确写法必须包含
GROUP BY,且所有非聚合字段(如region、product_type)都要列在GROUP BY后 - 如果只想要总销售额(不分组),就别选其他字段:
SELECT SUM(sales) FROM orders; - MySQL 5.7+ 默认开启
sql_mode=ONLY_FULL_GROUP_BY,强制校验,关掉它只是掩耳盗铃,不解决逻辑问题
多字段分组时,GROUP BY 顺序不影响结果,但影响排序
GROUP BY region, product_type 和 GROUP BY product_type, region 计算出的分组结果完全一致,SUM 值不会变。但如果你没加 ORDER BY,数据库返回顺序可能不同——这容易让人误以为结果错了。
- 分组逻辑只看字段组合是否相同,跟书写顺序无关
- 想让结果按地区优先排列,就写
GROUP BY region, product_type ORDER BY region, product_type - 注意:
ORDER BY必须写在GROUP BY之后,不能颠倒 - 某些旧版 SQLite 对多字段
GROUP BY兼容性差,建议升级到 3.7.11+
NULL 值会被 SUM 自动忽略,但要注意 WHERE 过滤时机
SUM() 天然跳过 NULL,这点没问题。但很多人把过滤条件写在 HAVING 里,而不是 WHERE,导致性能浪费或逻辑错误。
- 想排除无效订单(
status = 'cancelled'),必须用WHERE status != 'cancelled'—— 它在分组前过滤行 -
HAVING SUM(sales) > 1000是对分组后的结果再筛选,不能替代WHERE - 如果
sales字段本身为NULL,SUM()就当它不存在;但COUNT(*)仍会计数,这点常被混淆 - 需要把
NULL当 0 处理?用SUM(COALESCE(sales, 0))
用窗口函数替代 GROUP BY 实现“带明细的汇总”
有时候你既要每行原始数据,又想看到该组的销售总额——这时 GROUP BY 不行,得用窗口函数。
SELECT *, SUM(sales) OVER (PARTITION BY region) AS region_total FROM orders;-
PARTITION BY相当于分组,但不压缩行数,适合报表类需求 - MySQL 8.0+、PostgreSQL 9.4+、SQL Server 2005+ 支持;SQLite 3.25+ 也支持,但语法稍异
- 注意:窗口函数不能和普通聚合函数混用在同一层级,比如
SELECT region, SUM(sales), SUM(sales) OVER(...)会报错,必须用子查询或 CTE 拆开

















