AVG 是什么
AVG 计算平均值,分母是参与计算的非 NULL 值个数,而不是表的行数。它与“总和除以行数”是两个不同口径:只要列里有 NULL,两个结果就不一样。报表里说“平均”之前,先要确定用哪一个分母。
基本信息
| 计算方式 | 非 NULL 值之和除以非 NULL 值个数 |
|---|---|
| NULL 处理 | NULL 行不参与分子也不参与分母 |
| 整数平均 | MySQL 返回带小数的结果;PostgreSQL 的 AVG(integer) 返回 numeric |
| 空集 | 没有任何非 NULL 值时返回 NULL,而不是 0 |
| 自己算比率 | 分母用 NULLIF(x, 0) 防除零 |
| DISTINCT | AVG(DISTINCT col) 先去重再平均,口径完全不同 |
三种口径对比
三种口径对比
SELECT AVG(amount) AS avg_non_null, -- 只算有金额的行
SUM(amount) / COUNT(*) AS avg_all_rows, -- NULL 行也算分母
SUM(amount) / NULLIF(COUNT(amount), 0) AS avg_safe -- 与 AVG 等价且防除零
FROM orders
WHERE user_id = 42;
-- 三个值的差异全部来自分母定义,报表说明里必须写清用的是哪一种口径与适用
| 表达式 | 分母 | 适用场景 |
|---|---|---|
| AVG(col) | 非 NULL 值个数 | 只统计有值的记录 |
| SUM(col)/COUNT(*) | 全部行数 | 把缺失值也当作一笔业务 |
| SUM(col)/NULLIF(COUNT(col),0) | 非 NULL 值个数,且防除零 | 自己拼口径时最稳 |
| AVG(DISTINCT col) | 去重后的非 NULL 个数 | 看取值分布而非业务量 |
典型使用场景
- 统计客单价、平均时长、平均响应时间
- 按天或按渠道算平均指标,用于趋势对比
- 与 SUM、COUNT 并列,交叉验证报表数字
- 配合 CASE 做条件平均,例如只算已支付订单的平均金额
- 对比不同分母口径,判断缺失值对指标的影响
- 作为异常检测的基线,例如计算滑动窗口内的平均值
- 与中位数对比:平均值容易被极端值拉偏,关键指标建议两者一起看
- 分组后逐个渠道算平均,发现某个渠道明显异常时再下钻明细
AVG 忽略 NULL 是标准行为:如果业务上“缺失应记为 0”,要先 COALESCE(col, 0) 再求平均,否则结果偏高,偏高多少取决于缺失比例。
平均值对极端值敏感:一笔超大订单就能把客单价拉高很多。做经营分析时通常要同时看平均值、中位数与最大值,单看平均值容易得出错误结论。
空集上 AVG 返回 NULL:接口或报表直接展示会显示空白或取值报错。展示前用 COALESCE 兜底,并在文档里区分“无数据”与“平均值为 0”。