NULL 与 0 的差别
NULL 表示未知、未发生或源系统没有提供,0 表示业务上真实发生且取值为零,两者语义完全不同。混用会让平均值、占比与覆盖率同时失真:聚合函数默认忽略 NULL,一旦用 coalesce 统一填零,就把「没有发生」变成了「发生了但为零」。正确做法是在明细层完整保留 NULL,把补零只当展示约定处理,并在指标卡里写清分母用的是非空样本还是全量行数。
基本信息
| NULL | 未知、未发生或源未提供 |
|---|---|
| 0 | 业务上真实发生的零值 |
| 受影响指标 | 平均值、占比、非空率、覆盖率 |
| 处理原则 | 明细保留 NULL,展示层单独约定 |
| 校验 | 总行数、空值数、零值数分开统计 |
典型使用场景
- 区分「当日无销售」与「当日销售额为零」,两者在波动检测里含义不同
- 覆盖率类指标(有手机号的客户占比)必须用非空计数做分子
- 质量巡检把空值率与零值率分开看,避免把缺失当成业务下滑
- 上游用空字符串或特殊编码表示缺失时,在接入层统一转成 NULL
- 报表补零展示前,先确认下游口径是否需要保留缺失信息
分开统计三类
分开统计三类
-- 全量行、空值、零值分开统计,语义一目了然
SELECT count(1) AS rows_all,
sum(CASE WHEN amt IS NULL THEN 1 ELSE 0 END) AS rows_null,
sum(CASE WHEN amt = 0 THEN 1 ELSE 0 END) AS rows_zero,
avg(amt) AS avg_non_null,
sum(amt) / count(1) AS avg_with_zero
FROM dwd_order
WHERE dt = '2026-10-12';四种情况对照
| 取值 | 含义 | 用错的表现 |
|---|---|---|
| NULL | 未知或未发生 | 填零后平均值被拉低 |
| 0 | 发生且取值为零 | 被当缺失剔除后指标虚高 |
| 空字符串 | 常见于源系统导出 | 关联匹配不到,产生伪缺失 |
| -1 等占位值 | 源系统特殊编码 | 参与计算后出现极端离群 |
avg 与 sum 都会忽略 NULL,但除法的分母不会自动忽略,所以「sum 除以全量行数」和「sum 除以非空行数」是两个不同的数,必须提前约定用哪一个。
把 NULL 显示为 0 是展示层约定,不要直接在明细表里改写,否则后续无法回溯究竟有多少条数据是缺失的。