聚合与窗口函数54 条

SUM 求和

对数值列求和,忽略 NULL;没有任何行或全为 NULL 时返回 NULL,报表场景常用 COALESCE 兜底。

SQL 速查数据更新于 2026-10-13

SUM 是什么

SUM 对数值列求和,忽略 NULL。它有一个容易被忽视的行为:没有任何行、或者所有行该列都是 NULL 时返回 NULL,而不是 0,报表里通常用 COALESCE 兜底。这与 COUNT 在无数据时返回 0 不同。SUM 还有 DISTINCT 变体 SUM(DISTINCT col),语义是先去重再求和,用之前要先想清楚业务含义。金额求和务必使用 DECIMAL 这类定点类型,浮点累加会累积精度误差。

基本信息

作用对数值列求和,忽略 NULL
无数据时返回 NULL,与 COUNT 返回 0 不同
DISTINCT 变体SUM(DISTINCT col) 先去重再求和
类型整数与 DECIMAL 保持精确,FLOAT 与 DOUBLE 是近似值
配合窗口函数SUM(x) OVER (…) 可算累计值与组内合计
适用平台标准 SQL,MySQL 8.0 与 PostgreSQL 一致

典型使用场景

  • 金额合计:订单总额、对账金额、月度营收
  • 累计求和:滚动余额与累计销量
  • 分组汇总:按天、按类目、按渠道求总额
  • 占比分母:SUM(x) OVER () 得到全局合计做占比
  • 条件求和:只把满足条件的行计入合计
  • 核对数据:与上游系统或明细加总的结果比对

示例

示例
SELECT COALESCE(SUM(amount), 0)                          AS total,      # 无数据时给 0
       SUM(IF(status = 'paid', amount, 0))               AS paid_total  # 条件求和
FROM orders
WHERE created_at >= '2024-05-01'
  AND created_at <  '2024-06-01';

-- PostgreSQL 的条件求和写法
SELECT SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS paid_total
FROM orders;

SUM 的行为细节

场景结果说明
无匹配行NULL报表需 COALESCE 兜底
列全为 NULLNULL不是 0
部分行该列为 NULL忽略这些行不计入也不报错
SUM(DISTINCT col)去重后求和语义与直觉可能不同
含浮点类型近似结果金额应改用定点类型
SUM 与 COUNT 在无数据时的返回值不同:一份报表里混用两者时,要分别处理 0 与 NULL,避免前端显示异常。
用 FLOAT 或 DOUBLE 累加金额会产生精度误差,几十万行累加后偏差可见,金额一律用 DECIMAL 或 numeric。
窗口形式的 SUM(x) OVER (ORDER BY d) 默认是从分区开头到当前行的累计值,想算组内总量要省略 ORDER BY。
求和结果要带明确口径:金额保留两位、数量取整、是否包含退款与取消,先把口径写进报表说明再写 SQL,能省掉大量返工。
SUM 的结果类型会随数据一起扩张:整数列在大批量数据上求和可能溢出,注意列类型上限,必要时用更大的整型或 DECIMAL。

易错点

  • 以为无数据时 SUM 返回 0,实际返回 NULL,报表显示空白
  • 金额列使用浮点类型,累加后出现小数位偏差,对账对不上
  • 条件求和写成 SUM(col) 加 WHERE,导致其他口径的行直接被过滤掉
  • 在连接放大的结果集上求和,金额被重复累加
  • 把 SUM(DISTINCT col) 当成普通求和用,重复值被意外去掉

数据来源与参考

  • MySQL 8.0 Reference Manual · SUM
  • PostgreSQL Documentation · Aggregate Functions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌