在 SQL 开发中,条件逻辑处理是绕不开的核心需求:状态转中文、数据分级、多条件分类统计、空值兜底、复杂业务筛选等。
很多开发者遇到多条件判断,只会写IF 函数,面对多分支、批量数据处理时束手无策,甚至只能查出来数据在代码层循环判断,极大降低查询效率。
而 CASE WHEN 作为 MySQL 万能条件语法,可以完美解决绝大多数 SQL 条件场景,支持多分支、嵌套判断、分组聚合统计,是高阶 SQL 开发的必备技能。今天这篇博文从零到实战讲透,所有案例可直接项目复用。
一、前置认知:CASE WHEN 是什么?
CASE WHEN 是 MySQL 标准的条件分支语法,作用类似于代码中的 if-else if-else,可以在 SELECT、WHERE、GROUP BY、ORDER BY 等场景使用。
核心优势:
- 支持多分支条件判断,远超 IF 单双分支能力
- 纯 SQL 层处理数据分类,减少代码循环逻辑
- 可结合聚合函数做复杂统计,适配报表业务
- 语法通用,兼容 MySQL、Oracle、PostgreSQL 等主流数据库
二、两种核心语法结构(必学)
CASE WHEN 分为 简单等值匹配 和 复杂条件匹配 两种写法,覆盖所有业务场景。
1. 简单写法:等值匹配(固定字段判断)
适用于:单个字段固定等值判断,语法简洁,可读性高。
语法模板:
CASE 字段名
WHEN 匹配值1 THEN 结果1
WHEN 匹配值2 THEN 结果2
ELSE 默认结果
END
2. 标准写法:复杂条件匹配(推荐)
适用于:范围判断、多字段组合判断、模糊匹配、非等值判断,开发90%场景优先使用,灵活性拉满。
语法模板:
CASE
WHEN 条件表达式1 THEN 结果1
WHEN 条件表达式2 THEN 结果2
ELSE 默认结果
END
💡 核心规则:条件从上到下依次匹配,命中即终止,未匹配任何条件则走 ELSE 默认值;无 ELSE 且未匹配,返回 NULL。
三、入门实战:基础字段转换(最常用)
日常开发中最常用场景:数据库存储数字状态,查询时转为中文展示,无需代码处理。我们以订单表 order 为例,订单状态字段 status:0=待支付,1=已支付,2=已发货,3=已完成,4=已取消。
示例1:简单等值写法实现状态转义
SELECT
id,
order_no,
status,
CASE status
WHEN 0 THEN '待支付'
WHEN 1 THEN '已支付'
WHEN 2 THEN '已发货'
WHEN 3 THEN '已完成'
ELSE '已取消'
END AS status_name
FROM `order`;
示例2:复杂条件写法(适配范围判断)
如果需要根据订单金额划分订单等级,等值写法无法实现,标准写法轻松搞定:
SELECT
id,
order_no,
amount,
CASE
WHEN amount < 100 THEN '小额订单'
WHEN amount BETWEEN 100 AND 1000 THEN '普通订单'
WHEN amount > 1000 THEN '大额订单'
ELSE '未知订单'
END AS order_level
FROM `order`;
四、高阶实战:分组统计(报表核心)
CASE WHEN 真正的核心价值:结合 SUM/COUNT 实现行转列、分类统计,是后台报表、数据统计的刚需用法,彻底替代复杂子查询。
场景:统计各状态订单数量、总金额
SELECT
-- 统计待支付订单数
COUNT(CASE WHEN status = 0 THEN id END) AS wait_pay_num,
-- 统计已支付订单数
COUNT(CASE WHEN status = 1 THEN id END) AS paid_num,
-- 统计已取消订单数
COUNT(CASE WHEN status = 4 THEN id END) AS cancel_num,
-- 统计大额订单总金额
SUM(CASE WHEN amount > 1000 THEN amount ELSE 0 END) AS big_order_amount
FROM `order`;
原理说明:条件命中返回订单ID,未命中返回 NULL,COUNT 自动忽略 NULL 值,精准实现分类统计。
场景:按条件分组统计用户等级人数
SELECT
CASE
WHEN total_consume < 500 THEN '普通用户'
WHEN total_consume BETWEEN 500 AND 2000 THEN 'VIP用户'
ELSE '超级VIP用户'
END AS user_level,
COUNT(id) AS user_num
FROM user
GROUP BY user_level;
五、进阶用法:排序、筛选、空值处理
1. 自定义排序规则(ORDER BY + CASE)
默认排序无法满足自定义优先级,比如订单优先展示「已支付、待支付、已发货、已取消」,可通过 CASE 自定义排序权重:
SELECT id, order_no, status
FROM `order`
ORDER BY
CASE status
WHEN 1 THEN 1 -- 已支付优先
WHEN 0 THEN 2 -- 待支付次之
WHEN 2 THEN 3 -- 已发货
ELSE 4 -- 已取消最后
END ASC;
2. 条件筛选过滤(WHERE + CASE)
可在 WHERE 中结合 CASE 实现动态条件筛选,适配复杂业务过滤规则:
SELECT * FROM `order`
WHERE CASE
WHEN create_time > '2026-01-01' THEN amount > 0
ELSE status = 1
END;
3. 空值、异常数据兜底
替代多个 IF 判断,统一处理异常数据,让查询结果更规整:
SELECT
id,
amount,
CASE
WHEN amount IS NULL THEN 0
WHEN amount < 0 THEN 0
ELSE amount
END AS safe_amount
FROM `order`;
六、CASE WHEN 嵌套用法(复杂业务适配)
面对双层、多层业务判断,支持 CASE WHEN 嵌套,适配复杂分级场景,比如:先判断订单状态,再根据金额分级。
SELECT
order_no,
status,
amount,
CASE
WHEN status IN (0,4) THEN '无效订单'
WHEN status IN (1,2,3) THEN
CASE
WHEN amount > 1000 THEN '有效大额订单'
ELSE '有效普通订单'
END
ELSE '未知订单'
END AS order_tag
FROM `order`;
💡 建议:嵌套层数不超过3层,否则可读性变差,可拆分业务逻辑优化。
七、高频避坑指南(新手必看)
坑1:忘记写 ELSE,出现 NULL 数据
如果所有条件都不命中,且无 ELSE 兜底,字段会返回 NULL,导致前端展示空白、统计数据异常。常规业务建议必加 ELSE 默认值。
坑2:条件顺序写错,匹配异常
CASE WHEN 从上至下匹配,命中即终止。如果先写大范围条件,后写小范围,会导致小范围失效。
错误示例:
CASE
WHEN amount > 0 THEN '普通订单'
WHEN amount > 1000 THEN '大额订单' -- 永远不会命中
END
正确写法:先写精准、大范围条件,后写宽泛条件
坑3:与 IF 函数混淆,滥用单分支判断
单条件判断可以用 IF(条件,真值,假值),但多分支场景必须用 CASE WHEN,代码更整洁、可维护性更高。
坑4:统计场景误用 SUM/COUNT
分类统计时,COUNT 场景无需加 ELSE 0,SUM 场景必须加 ELSE 0,否则 NULL 参与求和会导致数据错误。
八、CASE WHEN VS IF 函数 对比总结
| 特性 | CASE WHEN | IF 函数 |
|---|---|---|
| 分支数量 | 支持多分支(无限层级) | 仅支持二分支 |
| 使用场景 | 数据分类、报表统计、复杂排序 | 简单二元判断 |
| 兼容性 | 所有数据库通用 | 仅MySQL等少数数据库支持 |
| 可读性 | 多条件逻辑清晰,层级分明 | 多嵌套后代码混乱 |
九、文末总结
1. CASE WHEN 分为简单等值写法和复杂条件写法,复杂业务优先使用标准条件写法;
2. 核心场景:状态转义、数据分级、分类统计、自定义排序、异常数据兜底;
3. 匹配规则:从上到下命中即终止,条件顺序优先级极高;
4. 报表统计首选 CASE WHEN + 聚合函数,大幅简化 SQL,提升查询效率;
5. 多分支场景放弃 IF 函数,统一使用 CASE WHEN,代码更规范通用。
本文所有案例均为生产级可直接复用代码,收藏此文,后续开发遇到条件判断、数据统计场景,直接套用即可!