zoukankan      html  css  js  c++  java
  • CASE表达式

    case表达式的两种写法

    • 简单case表达式
    CASE sex
        WHEN '1' THEN '男'
        WHEN '2' THEN '女'
    ELSE '其他' END
    
    • 搜索case表达式
    CASE WHEN SEX='1' THEN '男'
         WHEN SEX='2' THEN '女'
    ELSE '其他' END
    

    简单 CASE 表达式正如其名,写法简单,但能实现的事情比较有限。简单 CASE 表达式能写的条件,搜索CASE表达式也能写,推荐使用搜索case表达式。
    我们在编写SQL语句的时候需要注意,在发现为真的 WHEN子句时,CASE表达式的真假值判断就会中止,而剩余的WHEN子句会被忽略。为了避免引起不必要的混乱,使用WHEN子句时要注意条件的排他性。

    CASE表达式写法注意点:
    • 统一分支返回的数据类型
    • 不要忘了写 END
    • 养成写 ELSE 子句的习惯
      不写 ELSE 子句时,CASE表达式的执行结果是NULL。但是不写可能会造成“语法没有错误,结果却不对”这种不易追查原因的麻烦,所以最好明确地写上 ELSE 子句

    案例:统计人数

    pref_name population
    龙岩 500
    深圳 2000
    ...
    SELECT CASE pref_name
    						WHEN '龙岩'THEN '福建'
    						WHEN '厦门'THEN '福建'
    						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 '浙江'
    						WHEN '温州'THEN '浙江'
    						WHEN '丁波'THEN '浙江'
    				ELSE '其他' END;
    

    按人口等级划分:

    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;
    

    在group by时使用select中定义的别名(当oracle会报错):

    SELECT CASE pref_name
    						WHEN '龙岩'THEN '福建'
    						WHEN '厦门'THEN '福建'
    						WHEN '福州'THEN '福建'
    						WHEN '广州'THEN '广东'
    						WHEN '深圳'THEN '广东'
    						WHEN '汕头'THEN '广东'
    						WHEN '杭州'THEN '浙江'
    						WHEN '温州'THEN '浙江'
    						WHEN '丁波'THEN '浙江'
    				ELSE '其他' END AS district,
    				SUM(population)
    from PopTbl
    GROUP BY district;
    

    用一条sql进行不同条件统计:

    pref_name sex population
    北京 1 500
    北京 2 550
    上海 1 600
    上海 2 450
    统计结果:
    pref_name
    北京 500 550
    上海 600 450
    sql语句:
    SELECT pref_name,
    			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
    

    这里是将“行结构”的数据转换成了“列结构”的数据。除了SUM,COUNT、AVG等聚合函数也都可以用于将行结构的数据转换成列结构的数据,其实就是在SELECT子句进行条件分支。

    UPDATE 语句里进行条件分支

    1.对工资为10000的降薪10%
    2.对工资低于8000高于5000的涨薪20%
    如果分两次执行,可能造成一些数据重复执行,所以要一次执行

    update Salaries
        set salary = case when salary >=1000 then salary * 0.9
                     case when salary>=5000 and salary<=8000 then salary*1.2 
                     else salary end;
    

    SQL 语句最后一行的 ELSE salary 非常重要,必须写上。因为如果没有它,条件 1 和条件2都不满足的员工的工资就会被更新成 NULL 。

    这个技巧的应用范围很广。例如,可以用它简单地完成主键值调换这种繁重的工作:

    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')
    

    联表匹配数据:

    -- 课程一览
    CREATE TABLE CourseMaster
    (course_id   INTEGER PRIMARY KEY,
     course_name VARCHAR(32) NOT NULL);
    
    INSERT INTO CourseMaster VALUES(1, '会计入门');
    INSERT INTO CourseMaster VALUES(2, '财务知识');
    INSERT INTO CourseMaster VALUES(3, '簿记考试');
    INSERT INTO CourseMaster VALUES(4, '税务师');
    
    -- 开设的课程
    CREATE TABLE OpenCourses
    (month       INTEGER ,
     course_id   INTEGER ,
        PRIMARY KEY(month, course_id));
    
    INSERT INTO OpenCourses VALUES(200706, 1);
    INSERT INTO OpenCourses VALUES(200706, 3);
    INSERT INTO OpenCourses VALUES(200706, 4);
    INSERT INTO OpenCourses VALUES(200707, 4);
    INSERT INTO OpenCourses VALUES(200708, 2);
    INSERT INTO OpenCourses VALUES(200708, 4);
    

    生产交叉表:

    select course_name,
    	case when course_id in (select course_id from opencourses where month=200706)  
    	THEN "O" else 'x' end AS "6月",
    	case when course_id in (select course_id from opencourses where month=200707) 
    	THEN "O" else 'x' end AS "7月",
    	case when course_id in (select course_id from opencourses where month=200708) 
    	THEN "O" else 'x' end AS "8月"		 
    from CourseMaster;
    				
    

    也可以使用EXISTS,无论使用IN还是EXISTS ,得到的结果是一样的,但从性能方面来说, EXISTS更好。通过EXISTS进行的子查询能够用到“month,course_id”这样的主键索引,因此尤其是当表OpenCourses里数据比较多的时候更有优势

    给字符串加前缀
    -- 商品类型字段中的字符串加上前缀
    SELECT product_name,
     CASE product_type   -- 约束条件
    	WHEN '衣服'    THEN concat('666',product_type)
        WHEN '办公用品' THEN concat('777',product_type)
        WHEN '厨房用具' THEN concat('888',product_type)
        ELSE NULL  
    		 END AS abc_product_type
    FROM Product;
    

    concat()函数:将多个字符串连接成一个字符串。

    oracle和mysql提供了CASE表达式的简化函数:

    -- Oracle中使用DECODE代替CASE表达式
    SELECT product_name,
     DECODE(product_type, 
         '衣服', 'A :' | | product_type,
         '办公用品', 'B :' | | product_type,
         '厨房用具', 'C :' | | product_type,
        NULL) AS abc_product_type
     FROM Product;
    
    -- MySQL中使用IF代替CASE表达式
    SELECT  product_name,
    	IF( IF( IF(product_type = '衣服',  CONCAT('A:', product_type), NULL)
    						IS NULL AND product_type = '办公用品', CONCAT('B:', product_type), 
    				IF(product_type = '衣服',  CONCAT('A:', product_type), NULL))
    							IS NULL AND product_type = '厨房用具', CONCAT('C:', product_type), 
    							IF( IF(product_type = '衣服',  CONCAT('A:', product_type), NULL)
    						IS NULL AND product_type = '办公用品', CONCAT('B:', product_type), 
    				IF(product_type = '衣服',  CONCAT('A:', product_type), NULL))) AS abc_product_type
    	FROM Product;
    
  • 相关阅读:
    ms4w php配置xdebug
    转载: js 调用父窗口函数-iframe父窗口和子窗口相互的调用方法
    禁止apache列出站内目录
    块元素和行内元素之间的转换,overflow与visibility
    float浮动定位
    绝对定位和固定定位
    相对定位
    边框样式的设置
    div盒子模型
    CSS修饰表格
  • 原文地址:https://www.cnblogs.com/sanzashu/p/10986238.html
Copyright © 2011-2022 走看看