mysql学习—CASE表达式

1-1 CASE表达式

CASE表达式概述

注意事项:
(1)统一各分支返回的数据类型
(2)不要忘了写END
(3)养成写ELSE子句的习惯

/* 把县编号转换成地区编号(1) */
SELECT CASE pref_name
             WHEN '德岛' THEN '四国'
             WHEN '香川' THEN '四国'
             WHEN '爱媛' THEN '四国'
             WHEN '高知' THEN '四国'
             WHEN '福冈' THEN '九州'
             WHEN '佐贺' THEN '九州'
             WHEN '长崎' THEN '九州'
             ELSE '其他' END AS district,
       SUM(population)
  FROM PopTbl
 GROUP BY CASE pref_name
             WHEN '德岛' THEN '四国'
             WHEN '香川' THEN '四国'
             WHEN '爱媛' THEN '四国'
             WHEN '高知' THEN '四国'
             WHEN '福冈' THEN '九州'
             WHEN '佐贺' THEN '九州'
             WHEN '长崎' THEN '九州'
             ELSE '其他' END;

或者直接——> GROUP BY district

/* 按人口数量等级划分都道府县 */
SELECT CASE WHEN population < 100 THEN '01'
            WHEN population >= 100 AND population < 200 THEN '02'
            WHEN population >= 200 AND population < 300 THEN '03'
            WHEN population >= 300 THEN '04'
            ELSE NULL END AS pop_class,
       COUNT(*) AS cnt
  FROM PopTbl
 GROUP BY CASE WHEN population < 100 THEN '01'
               WHEN population >= 100 AND population < 200 THEN '02'
               WHEN population >= 200 AND population < 300 THEN '03'
               WHEN population >= 300 THEN '04'
               ELSE NULL END;

用一条SQL语句进行不同条件的统计

/* 用一条SQL语句进行不同条件的统计 */
SELECT pref_name,
       /* 男性人口 */
       SUM( CASE WHEN sex = '1' THEN population ELSE 0 END) AS cnt_m,
       /* 女性人口 */
       SUM( CASE WHEN sex = '2' THEN population ELSE 0 END) AS cnt_f
  FROM PopTbl2
 GROUP BY pref_name;

行结构转换为列结构

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

应用场景:假设某公司规定“女性员工工资必须20万日元以下”
命题:蕴含式的逻辑表达式 P->Q 描述为 “如果是女性员工,则工资是20万日元以下”。

/* 用CHECK约束定义多个列的条件关系 */
/* 蕴含式 */
CONSTRAINT check_salary CHECK
( CASE WHEN sex = '2'
       THEN CASE WHEN salary <= 200000
                 THEN 1 ELSE 0 END
       ELSE 1 END = 1 )

逻辑与 :P且Q 记作 P^Q
如果在CHECK约束中使用逻辑与,则该公司不能雇佣男性员工。

/* 用CHECK约束定义多个列的条件关系 */
/* 逻辑与 */
CONSTRAINT check_salary CHECK
( sex = '2' AND salary <= 200000 )

两者区别:逻辑与P^Q为真,则需要命题P和命题Q均为真,或者一个为真且另一个无法判定真假。也就是能在这家公司工作的是“女性员工,工资20万日元以下”或者工资无法确定的员工。
蕴含式 P->Q为真,则需命题P和命题Q均为真,或者P为假,或者P无法判断真假。也就是如果不满足是“女性”这个前提,则无需考虑工资约束。

在UPDATE语句进行条件分支

需求:以某数值型的列的当前值为判断对象,将其更新成别的值。

/* 用CASE表达式写正确的更新操作 */
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;

注意:如果CASE 表达式没有明确指定ELSE子句,执行结果会被默认处理为ELSE NULL。
应用范围:例如,可以简单完成主键值调换。调换主键值a和b,需要将主键值临时转换成中间值,需要3次update操作。但是如果使用case表达式,1次就可以做到。

/* 用CASE表达式调换主键值 */
UPDATE SomeTable
   SET p_key = CASE WHEN p_key = 'a'
                    THEN 'b'
                    WHEN p_key = 'b'
                    THEN 'a'
                    ELSE p_key END
 WHERE p_key IN ('a', 'b');

表之间的数据匹配

CASE表达式 优势在于能够判断表达式。也就是,在CASE 表达式,我们可以使用BETWEEN,LIKE和<、>等谓词组合,以及嵌套子查询的IN和EXISTS谓词。

/* 表的匹配:使用IN谓词 */
SELECT CM.course_name,
       CASE WHEN CM.course_id IN 
                    (SELECT course_id FROM OpenCourses 
                      WHERE month = 200706) THEN '○'
            ELSE '×' END AS "6月",
       CASE WHEN CM.course_id IN 
                    (SELECT course_id FROM OpenCourses
                      WHERE month = 200707) THEN '○'
            ELSE '×' END AS "7月",
       CASE WHEN CM.course_id IN 
                    (SELECT course_id FROM OpenCourses
                      WHERE month = 200708) THEN '○'
            ELSE '×' END  AS "8月"
  FROM CourseMaster CM;

或者

/* 表的匹配:使用EXISTS谓词 */
SELECT CM.course_name,
       CASE WHEN EXISTS
                    (SELECT course_id FROM OpenCourses OC
                      WHERE month = 200706
                        AND CM.course_id = OC.course_id) THEN '○'
            ELSE '×' END AS "6月",
       CASE WHEN EXISTS
                    (SELECT course_id FROM OpenCourses OC
                      WHERE month = 200707
                        AND CM.course_id = OC.course_id) THEN '○'
            ELSE '×' END AS "7月",
       CASE WHEN EXISTS
                    (SELECT course_id FROM OpenCourses OC
                      WHERE month = 200708
                        AND CM.course_id = OC.course_id) THEN '○'
            ELSE '×' END  AS "8月"
  FROM CourseMaster CM;

对比使用 IN 和 EXISTS ,结果一样,但是从性能上看,EXISTS更好。通过EXISTS进行子查询能够使用“month,course_id”主键索引。

扫描二维码关注公众号,回复: 5135379 查看本文章

在CASE表示式中使用聚合函数

应用场景:
01 获取只加入一个社团的学生的社团ID
02 获取加入了多个社团的学生的主社团ID

/* 在CASE表达式中使用聚合函数 */
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 StudentClub
 GROUP BY std_id;

CASE WHEN COUNT(*)=1…ELSE…
这样表达式表示“只加入一个社团还是加入了多个社团”这样的条件分支。
对聚合结果进行条件判断 :
a.使用having 子句
b.case表达式

猜你喜欢

转载自blog.csdn.net/weixin_43387060/article/details/86102705