订阅更新

SQL COALESCE 和 NULLIF 怎么用?

面试问 075 约 3 分钟读完 1 次阅读

本文目录
  1. 面试怎么回答
  2. COALESCE 不是“第一个有效值”
  3. NULLIF 最常见的用途是保护分母
  4. 兜底值不能覆盖真实值
  5. 还要注意类型一致
  6. 怎么选择?

面试怎么回答

COALESCE 返回第一个非 NULL 值,适合多来源取值和缺失兜底;NULLIF 在两值相等时返回 NULL,常用于把空字符串、哨兵值标准化,或保护除零分母。二者组合时我会写成 COALESCE(NULLIF(TRIM(col), ''), fallback),既保留真实值,也处理空串。但兜底不等于修复源数据,核心字段还要监控缺失率,并区分“无法计算”和真实的 0。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

一列渠道名称里同时出现 NULL、空字符串和 unknown;另一个指标计算转化率时,分母又可能是 0。

很多人会顺手加一个 COALESCE,但跑完才发现:空字符串还在,除零错误也没解决。

这两个函数经常一起出现,但职责不同:COALESCE 从左到右返回第一个非 NULL 值;NULLIF 在两个表达式相等时返回 NULL,否则返回第一个表达式。

COALESCE 不是“第一个有效值”

COALESCE(channel_name, '未知')

它只能兜底 NULL。空字符串 ''、数字 0、字符串 'null' 都不是 SQL NULL,不会被替换。

如果空字符串也应视为缺失,可以先标准化:

COALESCE(NULLIF(TRIM(channel_name), ''), '未知')

处理顺序是:先去掉首尾空格;如果结果为空字符串,NULLIF 把它变成 NULL;最后 COALESCE 返回“未知”。

清洗与兜底流程

NULLIF 最常见的用途是保护分母

pay_user_cnt * 1.0 / NULLIF(visit_user_cnt, 0)

当访问人数是 0 时,NULLIF(visit_user_cnt, 0) 返回 NULL,从而避免除零报错,结果通常为 NULL。

如果报表明确要求无分母时展示 0,可以再套一层:

COALESCE(
  pay_user_cnt * 1.0 / NULLIF(visit_user_cnt, 0),
  0
) AS conversion_rate

但这里要警惕:“无法计算”与“转化率确实为 0”不是同一个业务含义。 是否把 NULL 展示为 0,要由指标口径决定,不能为了页面好看直接填充。

兜底值不能覆盖真实值

生产改 SQL 时,一个常见错误是直接把字段写成固定值:

'default_id' AS material_id

这会把已有真实值也覆盖掉。真正的兜底应保留有效数据:

COALESCE(NULLIF(material_id, ''), 'default_id') AS material_id

如果 0 也是业务合法值,就不能把 NULLIF(material_id, 0) 当清洗模板。哨兵值必须依据字段定义确定。

还要注意类型一致

COALESCE 的候选表达式需要能归并到兼容类型。数值列用字符串 '未知' 兜底,可能报错或触发隐式转换。日期、数值、字符串应该分别使用同类型默认值,必要时显式 CAST。

另外,COALESCE 只能改善结果展示或下游兼容性,不能证明源数据已经完整。大量默认值可能把上游缺失悄悄隐藏。核心字段应同时保留缺失率监控,必要时增加 is_fallback 标识。

怎么选择?

  • 多个来源按优先级取值:COALESCE
  • 把某个特定哨兵值转为 NULL:NULLIF
  • 空字符串清洗后再兜底:NULLIF + COALESCE
  • 避免除零:分母使用 NULLIF
  • 无法计算是否再变成 0:由指标定义决定
刷题进度保存在当前浏览器