如果你已经了解 CASE,那你知道它可以直接把逻辑写进查询里。但其实 CASE 有两种写法。如果你用 CASE WHEN ...,那就是类似 if-else 的条件判断,而简单 CASE 更像其他语言里的 switch-case:它会把一个表达式和多个值比较,然后执行对应的分支。
当你要把某个字段和固定值比较时,这种写法更简洁直观。
简单 CASE 的语法
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE default_result
END
很简单:
expression—— 要和value1、value2等值比较的表达式或字段。THEN表示如果匹配就返回什么。ELSE—— 如果都不匹配就返回什么(可以省略,但最好别省)。
例子:学生成绩
假设有个 students 表,里面有个 grade 字段,存的是 2 到 5 的整数。我们想把分数转成文字显示。
SELECT
name,
grade,
CASE grade
WHEN 5 THEN '优秀'
WHEN 4 THEN '良好'
WHEN 3 THEN '及格'
WHEN 2 THEN '不及格'
ELSE '未知'
END AS 文字成绩
FROM students;
这里 CASE 会把 grade 字段的值和 2、3、4、5 这些固定值比较。
例子:商品类别代码
在 products 表里有个 category_code 字段,存的是像 'el'、'frn'、'bks' 这样的短标签。我们想显示可读的类别名称。
SELECT
product_name,
category_code,
CASE category_code
WHEN 'el' THEN '电子产品'
WHEN 'frn' THEN '家具'
WHEN 'bks' THEN '图书'
ELSE '其他'
END AS category_name
FROM products;
这种写法特别适合把“代码”转成“人话”来显示。
例子:月份名称
有时候我们想根据数字显示月份的中文名:
SELECT
EXTRACT(MONTH FROM order_date) AS month_number,
CASE EXTRACT(MONTH FROM order_date)
WHEN 1 THEN '一月'
WHEN 2 THEN '二月'
WHEN 3 THEN '三月'
WHEN 4 THEN '四月'
WHEN 5 THEN '五月'
WHEN 6 THEN '六月'
WHEN 7 THEN '七月'
WHEN 8 THEN '八月'
WHEN 9 THEN '九月'
WHEN 10 THEN '十月'
WHEN 11 THEN '十一月'
WHEN 12 THEN '十二月'
ELSE '未知'
END AS month_name
FROM orders;
这样用简单 CASE,数字 1 到 12 就能一目了然地变成中文月份。
简单 CASE 里处理 NULL
要注意,如果你和 NULL 比较,结果会是 NULL,因为 NULL = NULL —— 不是 true,而是未知。
NULL 的例子:
SELECT
user_id,
status,
CASE status
WHEN 'active' THEN '活跃'
WHEN 'blocked' THEN '已封禁'
WHEN NULL THEN '无状态' -- 不会生效!
ELSE '未知'
END AS 用户状态
FROM users;
别用 WHEN NULL,要用 ELSE,或者直接用搜索型 CASE(我们上节课讲过):
CASE
WHEN status IS NULL THEN '无状态'
...
和搜索型 CASE 的对比
| 特点 | 简单 CASE | 搜索型 CASE |
|---|---|---|
| 和具体值比较 | ✅ 很方便 | ❌ 不适合 |
| 条件灵活性(>, IS NULL) | ❌ 不行 | ✅ 可以 |
| 编程里的类比 | switch-case |
if-else |
实用场景
例子:申请状态可视化
| request_id | status |
|---|---|
| 101 | new |
| 102 | in_progress |
| 103 | done |
| 104 | cancelled |
| 105 | NULL |
SELECT
request_id,
CASE status
WHEN 'new' THEN '🟡 新建'
WHEN 'in_progress' THEN '🔵 处理中'
WHEN 'done' THEN '🟢 已完成'
ELSE '⚪ 未知'
END AS 状态标签
FROM requests;
| request_id | 状态标签 |
|---|---|
| 101 | 🟡 新建 |
| 102 | 🔵 处理中 |
| 103 | 🟢 已完成 |
| 104 | ⚪ 未知 |
| 105 | ⚪ 未知 |
这里 CASE 就像翻译器,把技术状态变成易懂(还挺可爱)的标签。如果状态未知或 NULL —— 用户会看到 ⚪「未知」。
例子:报表里的分类分组
| employee_id | name | department |
|---|---|---|
| 1 | Alex Lin | HR |
| 2 | Maria Chi | IT |
| 3 | Anna Song | IT |
| 4 | Otto Art | FIN |
| 5 | Jane Doe | HR |
| 6 | Max Gray | SALES |
| 7 | Zoe Black | IT |
| 8 | Tom Brown | FIN |
| 9 | Liam Park | NULL |
| 10 | Eva Gold | HR |
SELECT
CASE department
WHEN 'HR' THEN '人事'
WHEN 'IT' THEN '技术'
WHEN 'FIN' THEN '财务'
ELSE '其他'
END AS 部门名称,
COUNT(*) AS 员工数
FROM employees
GROUP BY
CASE department
WHEN 'HR' THEN '人事'
WHEN 'IT' THEN '技术'
WHEN 'FIN' THEN '财务'
ELSE '其他'
END;
结果:
| 部门名称 | 员工数 |
|---|---|
| 人事 | 3 |
| 技术 | 3 |
| 财务 | 2 |
| 其他 | 2 |
这里发生了什么:
- HR 部门的员工归到“人事”类别。
- IT 就是“技术”。
- FIN 就是“财务”。
- 其他的,包括 SALES 和 NULL,都归到“其他”。这种方式很适合做友好易懂的报表。
常见错误
- 忘了写
ELSE→ 如果都不匹配就会得到NULL。 - 和
NULL比较 → 不生效,要用IS NULL和搜索型CASE。 - 类型不兼容 → 比如
CASE grade WHEN '5',但grade是数字类型。
简单 CASE —— 当你要把一个值和一堆可能的值比较时,就是你的好帮手。它简洁、易读,特别适合文本分类、可视化、代码转文本、分组等场景。
如果你要判断区间、NULL 或更复杂的条件 —— 用搜索型 CASE。SQL 喜欢清晰。CASE 就是你让逻辑变清晰的利器。
GO TO FULL VERSION