← 返回题目列表

SQL 中 CASE WHEN 怎么用?常见场景有哪些?

高频 中等 第 10 / 28 题 更新于 2026/07/29
SQLCASE WHEN条件表达式

简化版

CASE WHEN 是 SQL 里的条件表达式,可以在查询结果、排序、聚合统计和更新语句中按条件返回不同值;它按条件顺序匹配,命中后返回对应结果。

详细版

CASE WHEN 常见写法是:

CASE
  WHEN condition1 THEN value1
  WHEN condition2 THEN value2
  ELSE default_value
END

它不是流程控制语句,而是表达式,因此可以放在 SELECTORDER BYGROUP BYHAVINGUPDATE SET 等位置。

典型场景包括:把状态码翻译成文案、按分数划等级、条件聚合统计、按业务优先级排序、批量更新不同值。面试时要强调 WHEN 顺序、ELSE 默认值、返回类型兼容,以及条件写在列上可能影响索引使用。

完整版教学

一、CASE WHEN 的本质是表达式

CASE WHEN 会根据条件返回一个值,所以它可以出现在需要“值”的位置。

SELECT
  id,
  score,
  CASE
    WHEN score >= 90 THEN 'A'
    WHEN score >= 80 THEN 'B'
    WHEN score >= 60 THEN 'C'
    ELSE 'D'
  END AS grade
FROM exams;

如果 score=85,第一条条件不满足,第二条满足,结果是 B。它的结果像普通列一样可以命名为 grade

记忆钩子:CASE WHEN 不是单独跑流程,而是在 SQL 里“算出一个值”。

二、两种写法:搜索 CASE 与简单 CASE

搜索 CASE 可以写任意布尔条件:

CASE
  WHEN amount >= 1000 THEN 'large'
  WHEN amount >= 100 THEN 'medium'
  ELSE 'small'
END

简单 CASE 是拿一个表达式和多个值比较:

CASE status
  WHEN 0 THEN 'pending'
  WHEN 1 THEN 'paid'
  WHEN 2 THEN 'shipped'
  ELSE 'unknown'
END
类型适合场景特点
搜索 CASE范围判断、复合条件WHEN 后是条件
简单 CASE状态码枚举WHEN 后是匹配值
嵌套 CASE少量复杂分支可读性容易下降

面试中多数复杂场景使用搜索 CASE,因为它能表达 >=ANDOR 等条件。

三、条件顺序会影响结果

CASE WHEN 按顺序匹配,先命中的分支会返回结果,后面的分支不再决定最终值。

错误示例:

CASE
  WHEN score >= 60 THEN 'pass'
  WHEN score >= 90 THEN 'excellent'
  ELSE 'fail'
END

score=95 时会先命中 score >= 60,结果是 pass,不会得到 excellent

正确写法应把更具体、更严格的条件放前面:

CASE
  WHEN score >= 90 THEN 'excellent'
  WHEN score >= 60 THEN 'pass'
  ELSE 'fail'
END

这类题考的是条件覆盖关系,而不是语法本身。

四、条件聚合是高频用法

面试和业务报表里经常需要“一次扫描统计多个指标”,CASE WHEN 可以和聚合函数配合。

SELECT
  COUNT(*) AS total_orders,
  SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid_orders,
  SUM(CASE WHEN amount >= 1000 THEN 1 ELSE 0 END) AS large_orders
FROM orders;

如果有 1000 条订单,其中 700 条已支付、80 条金额不小于 1000,上面会返回:

total_orders | paid_orders | large_orders
1000         | 700         | 80

这种写法避免为了每个指标各查一遍表,在报表统计里很常见。

五、CASE WHEN 也能做业务排序

有些列表排序不是简单按时间或金额,而是按业务优先级。例如订单状态希望 paid 排前,其次 pending,最后 cancelled

SELECT id, status, created_at
FROM orders
ORDER BY
  CASE status
    WHEN 'paid' THEN 1
    WHEN 'pending' THEN 2
    WHEN 'cancelled' THEN 3
    ELSE 9
  END,
  created_at DESC;

排序权重可以画成:

paid -> 1
pending -> 2
cancelled -> 3
其他 -> 9

这个技巧常用于“置顶、推荐、处理中优先”等列表,但表达式排序可能无法直接利用普通索引,需要关注数据量和执行计划。

六、UPDATE 中的批量条件更新

CASE WHEN 还可以用于一次更新多种值。

UPDATE products
SET price = CASE
  WHEN category = 'book' THEN price * 0.9
  WHEN category = 'phone' THEN price * 0.95
  ELSE price
END
WHERE category IN ('book', 'phone');

如果书籍价格 100,会变成 90;手机价格 2000,会变成 1900。ELSE price 用来确保不命中的行保持原值。

实际写更新语句时要格外注意 WHERE 范围,避免全表都被计算。面试回答时可以补一句:大批量更新要分批、备份、在事务里验证影响行数。

七、常见误区与追问

  • 误区:CASE WHEN 是存储过程里的流程控制。 它在查询中是表达式,返回一个值。
  • 误区:WHEN 顺序无所谓。 分支按顺序匹配,范围条件写错顺序会改变结果。
  • 误区:可以省略 ELSE 且没有影响。 没有命中任何分支时结果通常为 NULL,可能影响展示和统计。
  • 误区:THEN 返回什么类型都可以随便混。 各分支返回类型应兼容,否则可能隐式转换或报错。
  • 追问:如何统计不同状态数量? 使用 SUM(CASE WHEN status = ... THEN 1 ELSE 0 END) 做条件聚合。
  • 追问:CASE WHEN 会影响索引吗? 放在过滤列或排序表达式上可能降低普通索引利用率,需要看执行计划。

八、加强记忆

CASE WHEN 当作 SQL 里的“条件算值器”:在 SELECT 里翻译字段,在聚合里统计指标,在 ORDER BY 里制造排序权重,在 UPDATE 里批量改不同值。写的时候盯住三件事:条件顺序、ELSE、返回类型。