sql case when 用法
下面用通俗一点的方式,把 SQLCASE WHEN 用法系统梳理一遍,适合日常开发快速上手和查阅。
1. CASE WHEN 是什么?
CASE WHEN 可以理解为 SQL 里的 “if / else if / else”
条件表达式,用来在查询时按条件返回不同的结果,而不需要改动原表数据。
常见用途:
- 按条件映射值(如 1/2 映射为 男/女)。
- 根据数值区间打标签(如分数→等级、年龄段)。
- 在聚合统计里做条件统计、条件求和。
2. 两种基本写法:简单 CASE vs 搜索 CASE
2.1 简单 CASE(Simple CASE)
语法(对“某个值”做等值匹配):
sql
CASE 表达式
WHEN 值1 THEN 结果1
WHEN 值2 THEN 结果2
...
ELSE 默认结果
END
示例:性别编码转中文。
sql
SELECT
user_id,
CASE sex
WHEN '1' THEN '男'
WHEN '2' THEN '女'
ELSE '其他'
END AS sex_name
FROM user;
特点:
- 相当于
switch...case,CASE后面跟的是一个“表达式”或字段值,然后用WHEN做等号比较。
- 适合 “1→男、2→女、3→未知” 这种枚举映射场景。
2.2 搜索 CASE(Searched CASE)
语法(每个 WHEN 都是一个完整条件):
sql
CASE
WHEN 条件1 THEN 结果1
WHEN 条件2 THEN 结果2
...
ELSE 默认结果
END
示例:按年龄打标签。
sql
SELECT
name,
age,
CASE
WHEN age < 18 THEN '未成年'
WHEN age BETWEEN 18 AND 60 THEN '成年人'
ELSE '老年人'
END AS age_group
FROM user;
特点:
CASE后面不跟表达式,每个WHEN里是完整逻辑条件(可以用>,<,=,BETWEEN,IN,AND,OR等)。
- 更灵活,基本等同于多层
if / else if / else。
3. 语法结构与细节规则
3.1 基本结构
无论哪种 CASE,整体结构都是:CASE 开始,END 结束,中间若干 WHEN ... THEN ...,可选 ELSE:
sql
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE else_result -- 可选
END
要点:
WHEN至少 1 个,可以有很多个。
ELSE可省略;如果省略且所有条件都不满足,返回NULL。
- 整个
CASE ... END在 SQL 中视为一个“表达式”,通常需要起别名。比如END AS age_group。
3.2 “匹配到第一个就停止”的规则
一个非常重要的点:CASE 从上到下判断,只返回第一个满足条件的结果,后面的不再执行 。
例子:
sql
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
ELSE 'C'
END
- 当
score = 95时,命中第一个条件(>= 90),直接返回 'A',不会再继续判断>= 80。
- 因此,条件要从“最严格/最具体”写到“最宽松” ,否则可能出现逻辑错误。
3.3 结果值类型需要兼容
- 同一个
CASE的各个THEN/ELSE返回值,最好是相同或可隐式转换为同一类型(比如全是字符串,或者全是数字)。
- 否则有的数据库会报类型错误,或者被强制转换成你意想不到的类型。
4. 常见使用场景示例
4.1 在 SELECT 子句中生成新字段
最常见:查询时直接生成标签字段或映射字段。
sql
SELECT
order_id,
amount,
CASE
WHEN amount >= 1000 THEN '大额订单'
WHEN amount >= 500 THEN '中额订单'
ELSE '小额订单'
END AS order_level
FROM orders;
4.2 在聚合统计中做条件统计(类似条件 COUNT / SUM)
很多教程会用 CASE WHEN + 聚合函数做“条件计数/求和”。
示例:统计男女及格人数。
sql
SELECT
COUNT(CASE WHEN sex = '1' AND score >= 60 THEN 1 END) AS male_pass,
COUNT(CASE WHEN sex = '2' AND score >= 60 THEN 1 END) AS female_pass
FROM exam;
或用 SUM:
sql
SELECT
SUM(CASE WHEN sex = '1' AND score >= 60 THEN 1 ELSE 0 END) AS male_pass,
SUM(CASE WHEN sex = '2' AND score >= 60 THEN 1 ELSE 0 END) AS female_pass
FROM exam;
4.3 行转列统计
在一些行转列统计里也经常用 CASE WHEN:比如把每个月的数据按列展开。
sql
SELECT
user_id,
SUM(CASE WHEN month = 1 THEN amount ELSE 0 END) AS m1_amount,
SUM(CASE WHEN month = 2 THEN amount ELSE 0 END) AS m2_amount,
...
FROM bills
GROUP BY user_id;
这种写法本质上就是“按条件求和”,顺带把行转成列展示。
4.4 结合子查询 / 不同表条件返回不同数据
有些文章示例会写类似:如果 type=1 从 A 表取图,如果 type=2 从 B 表取图,否则用默认图。
sql
SELECT
p.id,
CASE p.type
WHEN 1 THEN (SELECT b.img FROM post_book b WHERE b.pid = p.id)
WHEN 2 THEN (SELECT t.img FROM post_tool t WHERE t.pid = p.id)
ELSE 'default.png'
END AS img
FROM post p;
这种写法用在复杂业务逻辑中,可以在一条 SQL 里完成“分支查询”。
5. CASE WHEN 可以出现的位置
常见位置:
SELECT列中:最常见,用来生成计算列、标签列。
ORDER BY:实现自定义排序逻辑(如把“处理中”的排前面)。
GROUP BY中有些实现也支持(但要注意规范和兼容性)。
示例:自定义排序。
sql
SELECT
order_id,
status
FROM orders
ORDER BY
CASE status
WHEN 'processing' THEN 1
WHEN 'pending' THEN 2
WHEN 'done' THEN 3
ELSE 4
END;
6. 常见坑与注意事项
- 条件顺序错误
- 记住“命中第一个就停”,从“严”到“宽”排列条件。
- 忘记写 ELSE
- 某些情况你希望未命中的记录有明确值(比如 '未知'),否则返回
NULL,可能影响后续统计。
- 某些情况你希望未命中的记录有明确值(比如 '未知'),否则返回
- 类型不一致
- 不要在一个 CASE 里有的
THEN返回字符串,有的返回数字,容易出问题。
- 不要在一个 CASE 里有的
- 在某些数据库中不支持在 WHERE 中直接写复杂 CASE
- 一般推荐把复杂
CASE写在SELECT或ORDER BY,如果一定要在WHERE中做复杂逻辑,可拆成多个条件或用子查询。
- 一般推荐把复杂
7. 小结版记忆口诀
- 分两类:
- 简单 CASE:
CASE 字段 WHEN 值 THEN 结果 ...(类似 switch)。
- 简单 CASE:
* 搜索 CASE:`CASE WHEN 条件 THEN 结果 ...`(类似 if/else)。
- 四个关键词:
CASE→WHEN→THEN→ELSE(可选) →END。
- 一条规则:只返回第一个符合条件的结果 。
如果你方便给一个具体的业务场景(比如“根据成绩分等级并统计每个等级人数”或“订单状态自定义排序”),我可以按你常用的数据库方言(MySQL / SQL Server / PostgreSQL 等)帮你写一套更贴近实战的 CASE WHEN 模板。