case 表达式的基本用法
case when sex=1 then "男"
when sex=2 then "女"
else '其他' end
或者
case sex when 1 then "男"
when 2 then "女"
else '其他' end
注意事项
- 每个条件具有排他性,执行到符合条件的分支就不会继续执行下去。
- then后面返回的数据类型要一致。
- 不写else,执行不到符合条件的分支返回null。
使用示例:
根据条件聚合数据
mysql> select * from poptbl;
+-----------+------------+
| pref_name | population |
+-----------+------------+
| 东京 | 400 |
| 佐贺 | 100 |
| 德岛 | 100 |
| 爱媛 | 150 |
| 福冈 | 300 |
| 群马 | 50 |
| 长崎 | 200 |
| 香川 | 200 |
| 高知 | 200 |
+-----------+------------+
统计各个区域的人数
SELECT
(
CASE
WHEN pref_name IN ( "德岛", "香川", "爱媛", "高知" ) THEN
"四国"
WHEN pref_name IN ( "福冈", "佐贺", "长崎" ) THEN
"九州" ELSE "其他"
END
),
sum( population )
FROM
poptbl
GROUP BY
(
CASE
WHEN pref_name IN ( "德岛", "香川", "爱媛", "高知" ) THEN
"四国"
WHEN pref_name IN ( "福冈", "佐贺", "长崎" ) THEN
"九州" ELSE "其他"
END
);
结果:
+------+------+
| 区域 | 人数 |
+------+------+
| 九州 | 600 |
| 其他 | 450 |
| 四国 | 650 |
+------+------+
一条语句根据不同条件聚合数据,可以得到不同条件的多列数据
mysql> select * from poptbl2;
+-----------+-----+------------+
| pref_name | sex | population |
+-----------+-----+------------+
| 东京 | 1 | 250 |
| 东京 | 2 | 150 |
| 佐贺 | 1 | 20 |
| 佐贺 | 2 | 80 |
| 德岛 | 1 | 60 |
| 德岛 | 2 | 40 |
| 爱媛 | 1 | 100 |
| 爱媛 | 2 | 50 |
| 福冈 | 1 | 100 |
| 福冈 | 2 | 200 |
| 长崎 | 1 | 125 |
| 长崎 | 2 | 125 |
| 香川 | 1 | 100 |
| 香川 | 2 | 100 |
| 高知 | 1 | 100 |
| 高知 | 2 | 100 |
+-----------+-----+------------+
统计不同性别人数
SELECT
pref_name AS 地区,
sum( CASE WHEN sex = 1 THEN population ELSE 0 END ) AS 男,
sum( CASE WHEN sex = 2 THEN population ELSE 0 END ) AS 女
FROM
poptbl2
GROUP BY
pref_name;
结果
+------+------+------+
| 地区 | 男 | 女 |
+------+------+------+
| 东京 | 250 | 150 |
| 佐贺 | 20 | 80 |
| 德岛 | 60 | 40 |
| 爱媛 | 100 | 50 |
| 福冈 | 100 | 200 |
| 长崎 | 125 | 125 |
| 香川 | 100 | 100 |
| 高知 | 100 | 100 |
+------+------+------+
根据条件进行不同的数据更新
mysql> select * from salaries;
+------+--------+
| name | salary |
+------+--------+
| 木村 | 220000 |
| 相田 | 300000 |
| 神崎 | 270000 |
| 齐藤 | 290000 |
+------+--------+
条件:
- 对当前工资为 30 万日元以上的员工,降薪 10%。
- 对当前工资为 25 万日元以上且不满 28 万日元的员工,加薪 20%。
执行
UPDATE salaries SET salary = ( CASE WHEN salary > 300000 THEN
salary * 0.9
WHEN salary > 250000
AND salary < 280000 THEN
salary * 1.2 ELSE salary
END );
结果
mysql> select * from salaries;
+------+--------+
| name | salary |
+------+--------+
| 木村 | 220000 |
| 相田 | 300000 |
| 神崎 | 324000 |
| 齐藤 | 290000 |
+------+--------+
表聚合
mysql> select * from coursemaster;
+-----------+-------------+
| course_id | course_name |
+-----------+-------------+
| 1 | 会计入门 |
| 2 | 财务知识 |
| 3 | 簿记考试 |
| 4 | 税务师 |
+-----------+-------------+
4 rows in set (0.00 sec)
mysql> select * from opencourses;
+--------+-----------+
| month | course_id |
+--------+-----------+
| 200706 | 1 |
| 200706 | 3 |
| 200706 | 4 |
| 200707 | 4 |
| 200708 | 2 |
| 200708 | 4 |
+--------+-----------+
SELECT
course_name,
( CASE WHEN course_id IN ( SELECT course_id FROM opencourses WHERE MONTH = "200706" ) THEN 1 ELSE 0 END ) AS "6月",
( CASE WHEN course_id IN ( SELECT course_id FROM opencourses WHERE MONTH = "200707" ) THEN 1 ELSE 0 END ) AS "7月",
( CASE WHEN course_id IN ( SELECT course_id FROM opencourses WHERE MONTH = "200708" ) THEN 1 ELSE 0 END ) AS "8月"
FROM
coursemaster;
SELECT
course_name,
CASE
WHEN FIND_IN_SET( "200706", GROUP_CONCAT( MONTH ) ) THEN
TRUE ELSE FALSE
END AS "6月",
CASE
WHEN FIND_IN_SET( "200707", GROUP_CONCAT( MONTH ) ) THEN
TRUE ELSE FALSE
END AS "7月",
CASE
WHEN FIND_IN_SET( "200708", GROUP_CONCAT( MONTH ) ) THEN
TRUE ELSE FALSE
END AS "8月"
FROM
coursemaster AS cm
INNER JOIN opencourses AS oc ON oc.course_id = cm.course_id
GROUP BY
course_name;
结果
+-------------+-----+-----+-----+
| course_name | 6月 | 7月 | 8月 |
+-------------+-----+-----+-----+
| 会计入门 | 1 | 0 | 0 |
| 税务师 | 1 | 1 | 1 |
| 簿记考试 | 1 | 0 | 0 |
| 财务知识 | 0 | 0 | 1 |
+-------------+-----+-----+-----+
个人觉着这个 case when 其实就是根据条件做一次逻辑计算,替换指定的字段。按照这个想法去写 sql 即可。