首页 > 数据库 >关于 SQL 中的 CASE 表达式,你都知道那些妙用?

关于 SQL 中的 CASE 表达式,你都知道那些妙用?

时间:2022-12-22 21:22:31浏览次数:45  
标签:CASE 妙用 END WHEN ELSE course SQL id

CASE 表达式的妙用

1. 前言

CASE 表达式是从 SQL-92 标准开始被引入的。

在 CASE 表达式里,可以使用 BETWEEN 、LIKE和 < 、> 等便利的谓词组合,以及能嵌套子查询的 IN 和 EXISTS 谓词。

2. 语法

CASE 表达式有 简单 CASE 表达式(simple case expression)搜索 CASE 表达式(searched case expression) 两种写法:

-- 简单CASE 表达式
CASE sex
WHEN '1' THEN '男'
WHEN '2' THEN '女'
ELSE '其他'END


-- 搜索CASE 表达式
CASE WHEN sex = '1' THEN '男'
     WHEN sex = '2' THEN '女'
ELSE '其他' END
复制代码

sex 列(字段)如果是 '1' ,那么结果为男;如果是 '2' ,那么结果为女。

3. 注意点

CASE在匹配给定条件时,发现为真的 WHEN 子句时,CASE 表达式的真假值判断就会中止,而剩余的 WHEN 子句会被忽略。为了避免引起不必要的混乱,使用 WHEN 子句时要注意条件的排他性。

-- 例如,这样写的话,结果里不会出现“第二”
CASE WHEN col_1 IN ('a', 'b') THEN '第一'                
     WHEN col_1 IN ('a') THEN '第二'
ELSE '其他' END
复制代码
  1. 统一各分支返回的数据类型: 一定要注意 CASE 表达式里各个分支返回的数据类型是否一致。某个分支返回字符型,而其他分支返回数值型的写法是不正确的。
  2. 不要忘了写 END: 不写END是语法错误,这是不允许的。
  3. 养成写 ELSE 子句的习惯: 与 END 不同,ELSE 子句是可选的,不写也不会出错。不写 ELSE 子句时,CASE 表达式的执行结果是 NULL 。

4. 分类汇总数据:

Snipaste_2022-09-11_08-50-19.png

SELECT 
    CASE pref_name 
        WHEN '德岛' THEN '四国'
        WHEN '香川' THEN '四国'
        WHEN '爱媛' THEN '四国'
        WHEN '高知' THEN '四国'
        WHEN '福冈' THEN '九州'
        WHEN '佐贺' THEN '九州'
        WHEN '长崎' THEN '九州'
    END AS district,
    SUM(population) AS total
FROM poptbl
GROUP BY 
    CASE pref_name 
        WHEN '德岛' THEN '四国'
        WHEN '香川' THEN '四国'
        WHEN '爱媛' THEN '四国'
        WHEN '高知' THEN '四国'
        WHEN '福冈' THEN '九州'
        WHEN '佐贺' THEN '九州'
        WHEN '长崎' THEN '九州'
    END;
复制代码

5. 一条SQL实现不同条件的统计

Snipaste_2022-09-11_09-11-09.png

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 poptlb
GROUP By pref_name
复制代码

6. 使用CHECK约束定义多个列的条件关系

假设某公司规定“女性员工的工资必须在 20 万日元以下”,而在这个公司的人事表中,这条无理的规定是使用 CHECK 约束来描述的,代码如下所示:

CONSTRAINT check_salary CHECK ( 
    CASE WHEN sex = '2' THEN 
        CASE WHEN salary <= 200000
            THEN 1 ELSE 0 END
        ELSE 1 END = 1 
)
复制代码

7. 在UPDATE语句中进行条件分支

Snipaste_2022-09-11_09-35-15.png

条件:

  1. 对当前工资为 30 万日元以上的员工,降薪 10%。
  2. 对当前工资为 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;
复制代码

8. 生成交叉表

Snipaste_2022-09-11_16-01-05.png

Snipaste_2022-09-11_16-02-53.png

Snipaste_2022-09-11_16-04-04.png

--- 使用IN谓词
SELECT
    course_name AS '课程名',
    CASE WHEN courese_id IN (SELECT course_id FROM open_course WHERE mouth = '200706')
            THEN 'o' 
            ELSE 'x' 
    END AS '6 月'
    CASE WHEN courese_id IN (SELECT course_id FROM open_course WHERE mouth = '200707')
            THEN 'o' 
            ELSE 'x' 
    END AS '7 月'
    CASE WHEN courese_id IN (SELECT course_id FROM open_course WHERE mouth = '200708')
            THEN 'o' 
            ELSE 'x' 
    END AS '8 月'
FROM course_master;


--- 或者使用EXIST谓词
SELECT CM.course_name,
    CASE WHEN EXISTS (SELECT course_id FROM OpenCourses OC WHERE month = 200706 AND OC.course_id = CM.course_id) 
        THEN '○' ELSE '×' 
    END AS "6 月",
    CASE WHEN EXISTS (SELECT course_id FROM OpenCourses OC WHERE month = 200707 AND OC.course_id = CM.course_id) 
        THEN '○' ELSE '×' 
    END AS "7 月",
    CASE WHEN EXISTS (SELECT course_id FROM OpenCourses OC WHERE month = 200708 AND OC.course_id = CM.course_id) 
        THEN '○' ELSE '×' 
    END AS "8 月"
FROM CourseMaster CM;
复制代码

9. CASE表达式中使用聚合函数

Snipaste_2022-09-11_16-04-35.png

对于加入了多个社团的学生,通过将其“主社团标志”列设置为 Y 或者 N 来表明哪一个社团是他的主社团;对于只加入了一个社团的学生,将其“主社团标志”列设置为 N。

现需要查询出所有学生加入的社团,若加入了多个则显示主社团

SELECT 
    std_id,
    CASE WHEN COUNT(*)==1 THEN MAX(club_id) 
         ELSE MAX(CASE WHEN main_club_flg = 'Y' THEN club_id ELSE NULL END)
    END AS 'main_club'
FROM student_club
GROUP BY std_id
复制代码

10. 按照自定义规则排序列

image.png

按照mark列排序,要求修正a b c d 的权重为 c b a d

SELECT
    mark
FROM 
    sort_test
ORDER BY
    CASE mark
        WHEN 'a' THEN -1
        WHEN 'b' THEN 1
        WHEN 'c' THEN 2
        WHEN 'd' THEN -2
    END 
复制代码
来源:https://juejin.cn/post/7142033761197096990

标签:CASE,妙用,END,WHEN,ELSE,course,SQL,id
From: https://www.cnblogs.com/konglxblog/p/16999592.html

相关文章

  • Register sql server to azure arc
    registersqlservertoazurearcbutfailedwitherrors.pleasefollowbelowstepstotryandifitstillnotworkpleaseletmeknow,wecansetuparemotese......
  • MySQL锁机制
    1.表级锁&行级锁数据库中的锁通常分为两种:表级锁:对整张表加锁。开销小,加锁快,不会出现死锁。但是锁的粒度大,发生锁冲突的概率高,并发度低。行级锁:对某行记录加锁。开销大......
  • MySQL日志
    1.错误日志错误日志是MySQL中最重要的日志之一,它记录了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正......
  • SQL定义变量
    今天在使用MySQL的时候,发现需要使用定义一个变量才行。总结了如下的变量的特点1.变量的一般定义形式set@XXX=?;当然也是可以使用select的,但是没有这个简介>问题:变......
  • CMU15-445:Homework #1 - SQL
    Homework#1-SQL本文是对CMU15-445课程第1个作业文档的一个粗略翻译和完成。仅供个人(M1kanN)学习使用。1.Overview第一个作业要我们构建一组SQL查询,用于分析给定......
  • Springboot+Mybatis+MySql下,mysql使用json类型字段存取的处理
    转载:Springboot+Mybatis+MySql下,mysql使用json类型字段存取的处理背景:1、mysql5.7开始支持json类型字段;2、mybatis暂不支持json类型字段的处理,需要自己做处理项目......
  • SQL
      增删改查SELECTLastNameFROMPersons表包含带有数据的记录(行)。查询和更新指令构成了SQL的DML部分: SELECT-从数据库表中获取数据 UPDATE-更新数据库表......
  • mysql操作源码
    packagecom.mysql;importjava.sql.*;publicclassMysqlTest{staticfinalStringdriver="com.mysql.cj.jdbc.Driver";staticfinalStringDB="jdbc:mysql://......
  • Mysql主从配置
    Mysql主从配置什么是主从同步?俩台机器:主库,从库主库,写数据都写到主库中从库,从库主要用来读数据原理mysql主从配置的流程大体如下所示:1master会将变动记录到二进制......
  • 图文结合带你搞懂MySQL日志之Error Log(错误日志)
    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:KAiTO文章来源:社区原创往期回顾:图文......