首页/数据/SQL 速查/CASE 表达式(简单与搜索形式)

CASE 表达式(简单与搜索形式)

SQL 中的条件分支:简单 CASE 做等值匹配,搜索 CASE 书写任意条件;分支自上而下取首个命中,缺 ELSE 时返回 NULL。

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

CASE 表达式是什么

CASE 是 SQL 里的条件分支表达式,有两种写法:简单 CASE 拿一个表达式逐个与 WHEN 后面的值做等值比较,搜索 CASE 则在 WHEN 后面写任意布尔条件。分支自上而下取第一个命中,后面的分支不再判断;都不命中时返回 ELSE 的值,缺省 ELSE 就返回 NULL。它在报表里很实用:一次扫描就能同时算出多个口径的指标,也常用来把编码翻译成可读名称,或处理 NULL 这类特殊分支。

基本信息

简单 CASECASE expr WHEN v THEN r … END,用等值比较
搜索 CASECASE WHEN cond THEN r … END,条件任意写
匹配规则自上而下取首个命中,之后的分支不再判断
ELSE缺省时返回 NULL,建议显式写出
可写位置SELECT、WHERE、ORDER BY、GROUP BY 都可用
适用平台标准 SQL,MySQL 8.0 与 PostgreSQL 一致

典型使用场景

  • 编码翻译:把 status 数字转成中文名称
  • 分箱统计:按金额区间、分数段把记录归类
  • 一次算多口径:用几个 CASE 在同一查询里生成不同状态的计数
  • 条件排序:ORDER BY CASE WHEN 让指定记录置顶
  • 条件更新:UPDATE 时按不同条件写入不同值
  • 处理 NULL:用 CASE WHEN col IS NULL 单独分支

两种形式

两种形式
-- 简单 CASE:等值匹配
SELECT name,
       CASE level WHEN 1 THEN '低' WHEN 2 THEN '中' ELSE '高' END AS level_name
FROM tasks;

-- 搜索 CASE:任意条件,注意条件自上而下判断
SELECT score,
       CASE WHEN score >= 90 THEN 'A'
            WHEN score >= 80 THEN 'B'
            ELSE 'C' END AS grade
FROM exams;

一次算出多个口径

一次算出多个口径
SELECT city,
       COUNT(*)                                        AS total_cnt,
       SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END)      AS valid_cnt,   # 有效
       SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END)      AS pending_cnt, # 待审
       SUM(CASE WHEN phone IS NULL THEN 1 ELSE 0 END)   AS miss_phone   # 缺失
FROM users
GROUP BY city;

写法与注意

写法行为注意
简单 CASE等值比较判断 NULL 不会命中任何分支
搜索 CASE任意布尔条件条件要有顺序,先写更严格的
缺 ELSE返回 NULL未覆盖的分支会静默变空
CASE 里做聚合需要对每行输出值写成 SUM(CASE WHEN … THEN 1 ELSE 0 END)
简单 CASE 用等值比较,判断 NULL 时不会命中任何分支,因为 NULL = NULL 得到 UNKNOWN;需要判空要用搜索形式的 CASE WHEN col IS NULL。
忘记写 ELSE 时未覆盖的分支行会返回 NULL,统计报表里常表现为某些分类莫名少数据,写完先跑一遍各分支的行数分布。
条件排序要与业务口径一致:分数段判断必须从高到低写,先写 score >= 60 会把 90 分也归到及格档。

使用要点

  • ELSE 尽量显式写出,避免未覆盖分支静默变 NULL
  • 条件顺序从严格到宽松,避免被前面宽泛的分支截胡
  • 做条件计数时用 SUM(CASE WHEN … THEN 1 ELSE 0 END),比多次查询省资源
  • 分组前用 CASE 归类,可以让报表维度保持一致
  • 复杂分支写进子查询或 CTE,主查询只做汇总,可读性更好
  • 迁移数据库时注意 IF 与 IIF 这类专有函数不能直接搬

易错点

  • 简单 CASE 用等值比较,判断 NULL 不会命中任何分支,要用搜索形式 CASE WHEN col IS NULL
  • 忘记 ELSE 时未覆盖的行走 NULL 分支,统计报表里常表现为莫名少数据
  • 分支条件顺序写反,宽泛条件在前导致细分被吞掉
  • 把 CASE 写在 WHERE 里对列做转换,导致该列索引失效
  • 把数据库专有的 IF 或 IIF 当作 CASE 使用,跨库迁移时报错

数据来源与参考

  • MySQL 8.0 Reference Manual · CASE Expression
  • PostgreSQL Documentation · CASE
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌