MySQL中的case表达式

case 表达式 & case 语句

假如我们有一张表名为 employees ,如下所示:

复制代码
+-------------+------------+-----------+---------------+---------+------------+--------+
| employee_id | first_name | last_name | department_id | salary  | hire_date  | gender |
+-------------+------------+-----------+---------------+---------+------------+--------+
|           1 | John       | Doe       |             1 | 4500.00 | 2020-01-15 | M      |
|           2 | Jane       | Smith     |             2 | 5500.00 | 2019-03-22 | F      |
|           3 | Robert     | Brown     |             1 | 3500.00 | 2018-07-11 | M      |
|           4 | Emily      | Davis     |             3 | 2500.00 | 2021-05-17 | F      |
|           5 | Michael    | Wilson    |             2 | 7000.00 | 2017-11-05 | M      |
|           6 | Linda      | Taylor    |             3 | 4200.00 | 2020-10-25 | F      |
|           7 | David      | Anderson  |             1 | 4800.00 | 2019-08-19 | M      |
|           8 | Sarah      | Thomas    |             2 | 5100.00 | 2018-12-13 | F      |
|           9 | James      | Jackson   |             3 | 3100.00 | 2016-09-03 | M      |
|          10 | Patricia   | White     |             1 | 6000.00 | 2015-02-22 | F      |
+-------------+------------+-----------+---------------+---------+------------+--------+

case 表达式

CASE 表达式是用于在 SELECT 或其他查询语句中根据条件产生不同结果的方法。case 表达式有简单 case 表达式和搜索 case 表达式。(了解即可,实际上输出的结果是相同的)

基于员工的薪水(salary)字段返回不同的级别:

sql 复制代码
-- 搜索 case 表达式
SELECT first_name, last_name,
    CASE
        WHEN salary < 3000 THEN 'Low'
        WHEN salary >= 3000 AND salary < 5000 THEN 'Medium'
        WHEN salary >= 5000 THEN 'High'
        ELSE 'Unknown'
    END AS salary_level
FROM employees;

+------------+-----------+--------------+
| first_name | last_name | salary_level |
+------------+-----------+--------------+
| John       | Doe       | Medium       |
| Jane       | Smith     | High         |
| Robert     | Brown     | Medium       |
| Emily      | Davis     | Low          |
| Michael    | Wilson    | High         |
| Linda      | Taylor    | Medium       |
| David      | Anderson  | Medium       |
| Sarah      | Thomas    | High         |
| James      | Jackson   | Medium       |
| Patricia   | White     | High         |
+------------+-----------+--------------+
sql 复制代码
-- 简单 case 表达式
SELECT 
    first_name,
    last_name,
    CASE department_id
        WHEN 1 THEN 'HR'
        WHEN 2 THEN 'Engineering'
        WHEN 3 THEN 'Sales'
        ELSE 'Unknown'
    END AS department_name
FROM employees;

+------------+-----------+-----------------+
| first_name | last_name | department_name |
+------------+-----------+-----------------+
| John       | Doe       | HR              |
| Jane       | Smith     | Engineering     |
| Robert     | Brown     | HR              |
| Emily      | Davis     | Sales           |
| Michael    | Wilson    | Engineering     |
| Linda      | Taylor    | Sales           |
| David      | Anderson  | HR              |
| Sarah      | Thomas    | Engineering     |
| James      | Jackson   | Sales           |
| Patricia   | White     | HR              |
+------------+-----------+-----------------+
10 rows in set (0.00 sec)

注意点:

  1. else 子句可以不用写,但是不建议。养成良好的习惯。
  2. end 是必不可少的。

case 语句

CASE 语句是一种更通用的形式,可以在 SQL 中的任何位置使用,例如 SELECT、UPDATE、DELETE 语句中。

  • 与聚合函数结合使用。

统计每个部门的男性和女性员工数量:

sql 复制代码
SELECT 
    department_id,
    SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END) AS male_count,
    SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END) AS female_count
FROM employees
GROUP BY department_id;


+---------------+------------+--------------+
| department_id | male_count | female_count |
+---------------+------------+--------------+
|             1 |          3 |            1 |
|             2 |          1 |            2 |
|             3 |          1 |            2 |
+---------------+------------+--------------+
3 rows in set (0.01 sec)

case 语句不仅能写在聚合函数里面,还能写在聚合函数外面。

统计大部门和小部门:

sql 复制代码
SELECT department_id,
       CASE 
           WHEN COUNT(*) > 3 THEN 'big'
           ELSE 'small'
       END AS scale
FROM employees
GROUP BY department_id;

+---------------+-------+
| department_id | scale |
+---------------+-------+
|             1 | big   |
|             2 | small |
|             3 | small |
+---------------+-------+
3 rows in set (0.00 sec)
  • 在 UPDATE 语句里进行条件分支

假如让工资大于等于 5000 的降薪 20%,小于 5000 的涨薪 20%。你会怎么做?

首先最先想到的应该是两个UPDATE进行更新。但是有没有想过执行完第一个条件后,会对第二个进行干扰,从而出现错误的结果。

下面来看一个简单的方式来完成这个要求:

sql 复制代码
UPDATE employees
SET salary = 
    CASE
        WHEN salary >= 5000 THEN salary * 0.8  
        WHEN salary < 5000 THEN salary * 1.2 
    END;
    
-- 查询后的结果
+-------------+------------+-----------+---------------+---------+------------+--------+
| employee_id | first_name | last_name | department_id | salary  | hire_date  | gender |
+-------------+------------+-----------+---------------+---------+------------+--------+
|           1 | John       | Doe       |             1 | 5400.00 | 2020-01-15 | M      |
|           2 | Jane       | Smith     |             2 | 4400.00 | 2019-03-22 | F      |
|           3 | Robert     | Brown     |             1 | 4200.00 | 2018-07-11 | M      |
|           4 | Emily      | Davis     |             3 | 3000.00 | 2021-05-17 | F      |
|           5 | Michael    | Wilson    |             2 | 5600.00 | 2017-11-05 | M      |
|           6 | Linda      | Taylor    |             3 | 5040.00 | 2020-10-25 | F      |
|           7 | David      | Anderson  |             1 | 5760.00 | 2019-08-19 | M      |
|           8 | Sarah      | Thomas    |             2 | 4080.00 | 2018-12-13 | F      |
|           9 | James      | Jackson   |             3 | 3720.00 | 2016-09-03 | M      |
|          10 | Patricia   | White     |             1 | 4800.00 | 2015-02-22 | F      |
+-------------+------------+-----------+---------------+---------+------------+--------+
10 rows in set (0.00 sec)

这样看来就是很合理了。

case的用法不仅仅有这些,在case表达式里,我们可以使用BETWEEN,LIKE等等便利的谓词,以及能嵌套子查询的IN和EXISTS。

相关推荐
NPE~13 分钟前
CMDB科普:配置管理数据库——运维相关
运维·数据库·科普·cmdb·配置管理数据库
Highcharts.js19 分钟前
动态数据可视化架构:Highcharts + PHP + MySQL 从数据库到数据渲染
数据库·mysql·php·开发文档·实时数据·highcharts·图表开发
余槐i37 分钟前
WAL 下写并发仍是 1:SQLite 单写者模型实测与绕开方案
数据库·python·性能优化·sqlite·wal
阳光九叶草LXGZXJ9 小时前
达梦数据库-报错-15-列【XXX】长度超出定义
linux·运维·数据库·sql·学习
字节渡客10 小时前
Redis键明明过期了,业务还在读到旧数据
数据库·redis·spring
OnlineProxy12 小时前
亚马逊多账号运营:如何在规避“关联封号”风险的同时实现电商规模化扩张
服务器·数据库·redis
辻弋20113 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
可乐鸡翅yeah_14 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
石头麻辣鱼14 小时前
Bamboo 调度系统 OceanBase 适配实战:存储过程迁移踩过的三个大坑
数据库
龙亘川15 小时前
数智驱动民政升级 精准守护民生保障
大数据·数据库·人工智能