CASE WHEN 是用于字段值转换、条件过滤和聚合统计的SQL表达式,支持SELECT、WHERE、ORDER BY等子句,但需注意ELSE缺失、类型一致性和索引失效等问题。
直接在查询结果里动态改值,比如把数字状态码转成中文描述,不用在应用层处理。关键点是 CASE WHEN 是表达式,能用在 SELECT、ORDER BY、HAVING 甚至 WHERE(但要小心性能)里。
常见错误:漏写 ELSE,结果为 NULL 却没意识到;或者把字符串值写成不带引号的标识符,报错 Unknown column 'xxx'。
WHEN 后面是布尔表达式,不是列名匹配(除非写成 CASE status WHEN 1 THEN ... 这种简写形式)WHEN 条件按顺序匹配,遇到第一个为 TRUE 的就返回对应 THEN 值,后续不再判断THEN 返回值类型最好一致,否则 MySQL 会隐式转换,可能出意外(比如 THEN 0 和 THEN '未知' 混用,整列变成字符串)SELECT
id,
name,
CASE status
WHEN 1 THEN '启用'
WHEN 0 THEN '禁用'
ELSE '其他'
END AS status_text
FROM users;
不是所有场景都适合——MySQL 无法对含 CASE WHEN 的表达式有效使用索引,容易全表扫描。只建议用于低频、小数据量或条件逻辑复杂到 AND/OR 难以清晰表达的情况。
典型误用:把本该用 OR 拆开的多条件,硬套进一个 CASE WHEN 里,导致执行计划变差。
CASE WHEN 整体返回布尔值(即 TRUE/FALSE 或 1/0),例如 CASE WHEN type = 'A' THEN created_at > '2025-01-01' ELSE updated_at > '2025-01-01' END
(type = 'A' AND created_at > '2025-01-01') OR (type != 'A' AND updated_at > '2025-01-01')
CASE WHEN (type = 'A' AND created_at > ...) OR ...
这是 CASE WHEN 最高效、最推荐的用法之一。比子查询或多次 JOIN 轻量,且 MySQL 能较好优化。
容易忽略的点:在 SUM 里用 CASE WHEN 返回 0/1,比用 COUNT 更灵活(比如支持加权统计);但若漏写 ELSE 0,NULL 不参与 SUM 计算,结果偏小。
COUNT(CASE WHEN status = 1 THEN 1 END) 和 SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) 效果一样,但前者更语义清晰COUNT(CASE WHEN status = 1 AND last_login > DATE_SUB(NOW(), INTERVAL 7 DAY) THEN 1 END)
COUNT(CASE WHEN ... THEN id END)——万一 id 本身为 NULL,会被忽略SELECT COUNT(*) AS total, COUNT(CASE WHEN status = 1 THEN 1 END) AS active_count, AVG(CASE WHEN amount > 100 THEN amount END) AS avg_high_amount FROM orders;
两层以内还行,三层起就要警惕。调试困难、修改风险

真实项目里,一旦看到 CASE WHEN ... WHEN ... ELSE CASE WHEN ... END END,基本说明业务规则已超出 SQL 承载能力,该抽到应用层或用查找表替代。
CASE 字段更清楚ORDER BY 里嵌套太深,排序性能会明显下降WHEN/THEN/ELSE,否则 review 时极易看串行CASE WHEN,就让它只干一件事:转换、过滤或统计,别堆逻辑。越靠近业务规则中心的地方,越容易因一个小改动引发整条 SQL 行为偏移。