讲解

CASE WHEN 是 SQL 里的 if...else:在查询里按条件返回不同的值。完整形式是 CASE WHEN 条件1 THEN 值1 WHEN 条件2 THEN 值2 ELSE 默认值 END,从上往下逐个判断,命中第一个为真的 WHEN 就返回对应值,都不命中走 ELSE。它可以用在 SELECT 列表里给每行打标签,也可以用在 ORDER BY、WHERE 里。

CASE 有两种写法:搜索式(searched)像上面那样每个 WHEN 写完整条件,灵活通用;简单式(simple)把一个表达式放在 CASE 后面,WHEN 只写候选值:CASE status WHEN 'paid' THEN '已支付' ... END,适合做等值翻译。两种写法的选择标准和编程语言里 if...else 与 switch 的选择一样:范围判断用搜索式,枚举翻译用简单式。

CASE 最强大的场景是「条件聚合」:把 CASE 塞进 SUM、COUNT 里,一次查询统计出多个维度的指标。SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) 只累计已支付金额——一行 SQL 同时算出总单数、支付总额、待支付总额,不用跑三遍查询,是报表统计的看家技巧。

示例

给课程按价格分档:

SELECT title, price, CASE WHEN price >= 70 THEN '高价' WHEN price >= 50 THEN '中价' ELSE '平价' END AS price_level FROM courses ORDER BY price DESC;

简单式 CASE:把订单状态翻译成中文:

SELECT id, amount, CASE status WHEN 'paid' THEN '已支付' WHEN 'pending' THEN '待支付' WHEN 'cancelled' THEN '已取消' ELSE '未知' END AS status_text FROM orders;

条件聚合:一条 SQL 同时统计三种状态的单数与金额:

SELECT COUNT(*) AS total_orders,
  SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) AS paid_amount,
  SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS pending_amount,
  SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_count
FROM orders;

常见坑

  • 忘记 ELSE 又不覆盖所有情况:没有 ELSE 且没有 WHEN 命中时,CASE 返回 NULL——结果里莫名出现空值多半是这个原因。要么写 ELSE 兜底,要么确认 WHEN 穷尽了所有可能。
  • WHEN 顺序放错:CASE 从上往下短路执行,WHEN price >= 50 写在 WHEN price >= 70 前面,70 以上的永远进不了「高价」。范围条件要从严到宽排列。
  • 混淆两种写法的语法:CASE status WHEN 'paid' 后面不能再写 status = 'paid',简单式的 WHEN 只接受值。混着写是语法错误。
  • END 关键字漏写:每个 CASE 都必须以 END 收尾,嵌套 CASE 时尤其容易漏。格式化缩进能帮你看清配对关系。

小结

CASE WHEN 在查询内做分支:搜索式处理范围,简单式处理枚举,ELSE 兜底防 NULL;配合聚合函数是报表利器。下一节盘点常用的内置函数。