42 CASE
CASE 是 SQL 的条件表达式——最接近 if/else 的结构。它有两种形式。搜索式 CASE(CASE WHEN cond THEN ... END)会计算任意布尔条件。简单 CASE(CASE expr WHEN value THEN ... END)会将一个表达式与特定值进行比较。只要允许使用表达式,就可以使用 CASE——包括 SELECT、WHERE、ORDER BY、GROUP BY,以及聚合函数内部的表达式。
本章要点
- 用于一般条件的搜索式
CASE - 用于值相等判断的简单
CASE ELSE以及省略它时的结果- 使用
CASE将行按组分桶 CASE在条件聚合中的作用(以及FILTER何时可以替代它)
示例
搜索式是主力形式。PostgreSQL 按从上到下的顺序计算条件,并返回第一个为真的条件所对应的结果。如果没有条件匹配且没有 ELSE,结果就是 NULL——有时有用,有时会造成错误。
简单形式是相等比较的简写:CASE name WHEN 'a' THEN ... END 与 CASE WHEN name = 'a' THEN ... END 等价。当需要将多个离散值映射到结果时,这种写法很简洁。
条件聚合——只统计或求和匹配的行——过去需要使用 sum(CASE WHEN cond THEN val ELSE 0 END)。sum(val) FILTER (WHERE cond) 可以直接表达这个条件。当存在输入行但没有任何行匹配时,它可能返回 NULL,而 sum(CASE WHEN cond THEN val ELSE 0 END) 会返回 0。如果希望空结果为 0,请使用 COALESCE。
运行示例
运行方式:
常见陷阱
- 所有
THEN/ELSE分支都必须具有共同类型——CASE WHEN ... THEN 1 ELSE 'x' END会报错。混用类型时,请显式进行类型转换:CASE WHEN ... THEN 1::text ELSE 'x' END。 - 忘记
END是最常见的语法错误。 - 不写
ELSE时,如果没有分支匹配,结果就是NULL。如果这让人意外,请添加显式的ELSE ...。 - 在
WHERE中使用CASE虽然可行,但通常没有必要——大多数条件直接写成布尔表达式会更清楚。
CASE 和 COALESCE 有重叠之处,但并不相同。对于“第一个不是 NULL 的值”,COALESCE(a, b, c) 写起来更短;当条件不只是“是否为 NULL”时,CASE 更合适。
使用 CASE 将 id 映射为类似 ‘small’ / ‘medium’ / ’large’ 的标签,并按标签计数。在 ORDER BY 中使用 CASE,按自定义顺序排列优先级:ORDER BY CASE priority WHEN 'high' THEN 1 WHEN 'mid' THEN 2 ELSE 3 END。然后将 sum(CASE WHEN ...) 重写为 sum(...) FILTER (WHERE ...)。
下载
SQL 文件:case.sql · 全部示例文件 · 准备工作