MySql:Case的使用

语法

简单CASE表达式(比较固定值)

CASE 列名
    WHEN 值1 THEN 结果1
    WHEN 值2 THEN 结果2
    ELSE 默认结果
END

搜索式CASE表达式(可以使用复杂条件)

CASE 
    WHEN 条件1 THEN 结果1
    WHEN 条件2 THEN 结果2
    ELSE 默认结果
END

举例说明

Id name score
1 Alice 95
2 Bob 82
3 Charlie 73
4 David 60
5 Eva 45

上面是学生的成绩表,现在需要我们给学生的成绩分级:

-- AS grade 是给 "CASE WHEN score >= 90 THEN 'A' ......ELSE 'F' END" 这一列去别名(grade)
-- WHEN score >= 90 THEN 'A': 当score >= 90,那么 grade=A
-- ELSE 'F': 其他情况, grade=F

SELECT 
    name,
    score,
    CASE
        WHEN score >= 90 THEN 'A'  
        WHEN score >= 80 THEN 'B'
        WHEN score >= 70 THEN 'C'
        WHEN score >= 60 THEN 'D'
        ELSE 'F'
    END AS grade
FROM students;

最后的结果如下:

name score grade
Alice 95 A
Bob 82 B
Charlie 73 C
David 60 D
Eva 45 F

MySQL中CASE表达式的用法

1. 创建测试数据库和表

-- 创建数据库
CREATE DATABASE case_demo;
USE case_demo;

-- 创建产品表
CREATE TABLE products (
    product_id INT PRIMARY KEY AUTO_INCREMENT,
    product_name VARCHAR(50),
    price DECIMAL(10,2),
    stock_quantity INT
);

-- 创建员工表
CREATE TABLE employees (
    employee_id INT PRIMARY KEY AUTO_INCREMENT,
    employee_name VARCHAR(50),
    department_id INT,
    salary DECIMAL(10,2)
);

-- 创建订单表
CREATE TABLE orders (
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT,
    customer_type VARCHAR(10),
    order_date DATE,
    amount DECIMAL(10,2)
);

-- 创建任务表
CREATE TABLE tasks (
    task_id INT PRIMARY KEY AUTO_INCREMENT,
    task_name VARCHAR(50),
    priority VARCHAR(10),
    due_date DATE
);

-- 创建用户表
CREATE TABLE users (
    user_id INT PRIMARY KEY AUTO_INCREMENT,
    user_name VARCHAR(50),
    age INT
);

-- 创建学生成绩表
CREATE TABLE student_records (
    student_id INT PRIMARY KEY AUTO_INCREMENT,
    student_name VARCHAR(50),
    score INT,
    attendance_rate DECIMAL(3,2)
);

-- 创建订单详情表
CREATE TABLE order_details (
    detail_id INT PRIMARY KEY AUTO_INCREMENT,
    order_id INT,
    product_id INT,
    quantity INT,
    order_date DATE
);

2. 插入测试数据

-- 产品数据
INSERT INTO products (product_name, price, stock_quantity) VALUES
('iPhone 14', 6999.00, 50),
('小米电视', 3299.00, 120),
('华为笔记本', 5999.00, 30),
('普通鼠标', 59.00, 200),
('机械键盘', 299.00, 80);

-- 员工数据
INSERT INTO employees (employee_name, department_id, salary) VALUES
('张三', 1, 15000.00),
('李四', 2, 12000.00),
('王五', 3, 18000.00),
('赵六', 1, 16000.00),
('钱七', 4, 10000.00);

-- 订单数据
INSERT INTO orders (customer_id, customer_type, order_date, amount) VALUES
(101, 'VIP', '2023-05-15', 2999.00),
(102, '普通', '2023-06-20', 1599.00),
(103, 'VIP', '2023-07-01', 899.00),
(104, '普通', '2023-07-10', 599.00);

-- 任务数据
INSERT INTO tasks (task_name, priority, due_date) VALUES
('完成项目提案', '高', '2023-08-15'),
('更新用户手册', '中', '2023-08-20'),
('修复登录BUG', '高', '2023-08-10'),
('优化数据库', '低', '2023-08-30');

-- 用户数据
INSERT INTO users (user_name, age) VALUES
('用户A', 18),
('用户B', 25),
('用户C', 32),
('用户D', 22),
('用户E', 45),
('用户F', NULL);

-- 学生成绩数据
INSERT INTO student_records (student_name, score, attendance_rate) VALUES
('学生1', 95, 0.98),
('学生2', 85, 0.92),
('学生3', 88, 0.85),
('学生4', 72, 0.95),
('学生5', 65, 0.75);

-- 订单详情数据
INSERT INTO order_details (order_id, product_id, quantity, order_date) VALUES
(1, 1, 1, '2022-11-15'),
(1, 3, 2, '2023-01-15'),
(2, 2, 1, '2022-11-20'),
(3, 4, 5, '2023-02-01'),
(4, 5, 3, '2022-12-10'),
(4, 1, 1, '2023-03-05');

示例1:基础分类用法

SELECT 
    product_name,
    price,
    CASE 
        WHEN price < 50 THEN '低价商品'
        WHEN price BETWEEN 50 AND 200 THEN '中端商品'
        WHEN price > 200 THEN '高端商品'
        ELSE '未定价'
    END AS price_category
FROM products;

结果:

+--------------+---------+---------------+
| product_name | price   | price_category |
+--------------+---------+---------------+
| iPhone 14    | 6999.00 | 高端商品       |
| 小米电视     | 3299.00 | 高端商品       |
| 华为笔记本   | 5999.00 | 高端商品       |
| 普通鼠标     |   59.00 | 中端商品       |
| 机械键盘     |  299.00 | 高端商品       |
+--------------+---------+---------------+

示例2:简单CASE形式

SELECT 
    employee_name,
    CASE department_id
        WHEN 1 THEN '研发部'
        WHEN 2 THEN '市场部'
        WHEN 3 THEN '财务部'
        ELSE '其他部门'
    END AS department_name
FROM employees;

结果:

+--------------+----------------+
| employee_name | department_name |
+--------------+----------------+
| 张三         | 研发部         |
| 李四         | 市场部         |
| 王五         | 财务部         |
| 赵六         | 研发部         |
| 钱七         | 其他部门       |
+--------------+----------------+

示例3:在WHERE子句中使用

-- DATE_SUB('2023-07-20', INTERVAL 30 DAY) 是 MySQL 的日期函数,用于从指定日期 '2023-07-20' 减去 30 天。
--  '2023-07-20':起始日期。
--  INTERVAL 30 DAY:表示 30 天的时间间隔。
--  DATE_SUB:表示“日期减去间隔”。
-- 这个表达式的结果是 `2023-06-20`。
SELECT *
FROM orders
WHERE 
    CASE 
        WHEN customer_type = 'VIP' THEN order_date > DATE_SUB('2023-07-20', INTERVAL 30 DAY)
        ELSE order_date > DATE_SUB('2023-06-30', INTERVAL 7 DAY)
    END;

-- 如果customer_type = 'VIP',那么SQL就会变成
SELECT *
FROM orders
WHERE order_date > '2023-06-20'

结果:

+---------+-------------+---------------+------------+---------+
| order_id | customer_id | customer_type | order_date | amount  |
+---------+-------------+---------------+------------+---------+
|       3 |         103 | VIP           | 2023-07-01 | 899.00 |
|       4 |         104 | 普通           | 2023-07-10 |  599.00 |
+---------+-------------+---------------+------------+---------+

示例4:在ORDER BY中使用

SELECT *
FROM tasks
ORDER BY 
    CASE priority
        WHEN '高' THEN 1
        WHEN '中' THEN 2
        WHEN '低' THEN 3
        ELSE 4
    END;

结果:

+---------+-----------------+----------+------------+
| task_id | task_name       | priority | due_date   |
+---------+-----------------+----------+------------+
|       1 | 完成项目提案    | 高       | 2023-08-15 |
|       3 | 修复登录BUG     | 高       | 2023-08-10 |
|       2 | 更新用户手册    | 中       | 2023-08-20 |
|       4 | 优化数据库      | 低       | 2023-08-30 |
+---------+-----------------+----------+------------+

示例5:在UPDATE语句中使用

UPDATE products
SET price = 
    CASE 
        WHEN stock_quantity > 100 THEN price * 0.9  -- 库存多的打9折
        WHEN stock_quantity BETWEEN 50 AND 100 THEN price * 0.95  -- 中等库存打95折
        ELSE price * 1.05  -- 库存少的涨价5%
    END;

SELECT product_name, price FROM products;

结果:

+--------------+---------+
| product_name | price   |
+--------------+---------+
| iPhone 14    | 6649.05 |
| 小米电视     | 2969.10 |
| 华为笔记本   | 6298.95 |
| 普通鼠标     |   53.10 |
| 机械键盘     |  284.05 |
+--------------+---------+

示例6:在GROUP BY分组统计中使用

SELECT 
    CASE
        WHEN age < 20 THEN '20岁以下'
        WHEN age BETWEEN 20 AND 30 THEN '20-30岁'
        WHEN age > 30 THEN '30岁以上'
        ELSE '未知年龄'
    END AS age_group,
    COUNT(*) AS user_count
FROM users
GROUP BY age_group;

结果:

+------------+------------+
| age_group  | user_count |
+------------+------------+
| 20岁以下   |          1 |
| 20-30岁    |          2 |
| 30岁以上   |          2 |
| 未知年龄   |          1 |
+------------+------------+

-- 可以先这么理解:先不统计数量
SELECT 
    CASE
        WHEN age < 20 THEN '20岁以下'
        WHEN age BETWEEN 20 AND 30 THEN '20-30岁'
        WHEN age > 30 THEN '30岁以上'
        ELSE '未知年龄'
    END AS age_group
FROM users

结果:

+------------+
| age_group  |
+------------+
| 20岁以下   |
| 20-30岁    | 
| 30岁以上   |
| 20-30岁    | 
| 30岁以上   |
| 未知年龄   |
+------------

示例7:嵌套CASE表达式

SELECT 
    student_name,
    score,
    CASE
        WHEN score >= 90 THEN 'A'
        WHEN score >= 80 THEN 
            CASE 
                WHEN attendance_rate > 0.9 THEN 'B+'
                ELSE 'B'
            END
        WHEN score >= 70 THEN 'C'
        ELSE 'F'
    END AS grade
FROM student_records;

结果:

+--------------+-------+-------+
| student_name | score | grade |
+--------------+-------+-------+
| 学生1        |    95 | A     |
| 学生2        |    85 | B+    |
| 学生3        |    88 | B     |
| 学生4        |    72 | C     |
| 学生5        |    65 | F     |
+--------------+-------+-------+

示例8:与聚合函数结合使用

SELECT 
    product_id,
    SUM(CASE WHEN order_date >= '2023-01-01' THEN quantity ELSE 0 END) AS qty_2023,
    SUM(CASE WHEN order_date >= '2022-01-01' AND order_date < '2023-01-01' THEN quantity ELSE 0 END) AS qty_2022
FROM order_details
GROUP BY product_id;

结果:

+------------+-----------+-----------+
| product_id | qty_2023  | qty_2022  |
+------------+-----------+-----------+
|          1 |         1 |         1 |
|          2 |         0 |         1 |
|          3 |         2 |         0 |
|          4 |         5 |         0 |
|          5 |         0 |         3 |
+------------+-----------+-----------+

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com

×

喜欢就点赞,疼爱就打赏