SQL語句case when外用sum與count的區別

風靈使發表於2018-07-19

如下這個表TEST

  category | commdity | price
 ------------+------------+-------
  衣服        | T恤        |  1000
  辦公用品 | 打孔器   |   500
  廚房用具 | 菜刀       |  3000
  廚房用具 | 高壓鍋    |  6800
  廚房用具 | 叉子       |   500
  廚房用具 | 擦菜板    |   880
  辦公用品 | 圓珠筆    |   100
  衣服        | 運動T恤  |  4000

如果我想把商品按照1000元以下,1000-3000, 3000 以上分為三個檔次顯示出來,正確的語句是:

SELECT SUM (CASE WHEN price <= 1000 THEN 1 ELSE 0 END)AS low,
SUM (CASE WHEN price BETWEEN 1001 AND 3000 THEN 1 ELSE 0 END)AS mid,
SUM (CASE WHEN price > 3000 THEN 1 ELSE 0 END)AS high FROM TEST;

得出結果

  low | mid | high
 -----+-----+------
    5 |   1 |    2

當把上述語句的sum換成count時,得出結果:

  low | mid | high
 -----+-----+------
    8  |   8   |    8

如果只是用列來顯示,SELECT COUNT(price) FROM TEST WHERE price <= 1000 可以得出正確的結果:

 low 
 ----- 
  5  

所以用sum的結果是對的。
原因是什麼呢?
三個case語句效果相同,其實就是類似於增加一個欄位,這個欄位,滿足條件的為1,不滿足的是0,這樣sum的效果,就是將所有的1加起來,也就是所有滿足條件的記錄個數。

count,會不管是1還是0,都會統計,這樣怎麼算都是總條目數8個。


實現分組統計

如,我希望統計users表中每個建立者建立的男性、女性、無性別的使用者總數(資料表中有一個欄位creator_id,表示建立者的ID),語句如下:

select u.creator_id 建立者ID, 

sum( case u.sex when 1 then 1 else 0 end) 男性, 

sum( case u.sex when 2 then 1 else 0 end) 女性, 

sum( case when u.sex<>1 and u.sex<>2 then 1 else 0 end) 性別為空 

from users u group by u.creator_id;

Oracle CASE WHEN 用法介紹

1. CASE WHEN 表示式有兩種形式

--簡單Case函式  

CASE sex  
WHEN '1' THEN '男'  
WHEN '2' THEN '女'  
ELSE '其他' END  

--Case搜尋函式  

CASE
WHEN sex = '1' THEN '男'  
WHEN sex = '2' THEN '女'  
ELSE '其他' END  

2. CASE WHEN 在語句中不同位置的用法

2.1 SELECT CASE WHEN 用法

SELECT   grade, COUNT (CASE WHEN sex = 1 THEN 1      /*sex 1為男生,2位女生*/
                       ELSE NULL
                       END) 男生數,
                COUNT (CASE WHEN sex = 2 THEN 1
                       ELSE NULL
                       END) 女生數
    FROM students GROUP BY grade;

2.3 WHERE CASE WHEN 用法

SELECT T2.*, T1.*
   FROM T1, T2
  WHERE (CASE WHEN T2.COMPARE_TYPE = 'A' AND
                   T1.SOME_TYPE LIKE 'NOTHING%'
                THEN 1
              WHEN T2.COMPARE_TYPE != 'A' AND
                   T1.SOME_TYPE NOT LIKE 'NOTHING%'
                THEN 1
              ELSE 0
           END) = 1

2.4 GROUP BY CASE WHEN 用法

SELECT  
CASE WHEN salary <= 500 THEN '1'  
WHEN salary > 500 AND salary <= 600  THEN '2'  
WHEN salary > 600 AND salary <= 800  THEN '3'  
WHEN salary > 800 AND salary <= 1000 THEN '4'  
ELSE NULL END salary_class, -- 別名命名
COUNT(*)  
FROM    Table_A  
GROUP BY  
CASE WHEN salary <= 500 THEN '1'  
WHEN salary > 500 AND salary <= 600  THEN '2'  
WHEN salary > 600 AND salary <= 800  THEN '3'  
WHEN salary > 800 AND salary <= 1000 THEN '4'  
ELSE NULL END;  

3.關於IF-THEN-ELSE的其他實現

3.1 DECODE() 函式

select decode(sex, 'M', 'Male', 'F', 'Female', 'Unknown')
from   employees;

貌似只有Oracle提供該函式,而且不支援ANSI SQL,語法上也沒CASE WHEN清晰,個人不推薦使用。

3.2 在WHERE中特殊實現

SELECT T2.*, T1.*
   FROM T1, T2
  WHERE (T2.COMPARE_TYPE = 'A' AND T1.SOME_TYPE LIKE 'NOTHING%')
         OR
        (T2.COMPARE_TYPE != 'A' AND T1.SOME_TYPE NOT LIKE 'NOTHING%')

這種方法也是在特殊情況下使用,要多注意邏輯,不要弄錯。


oraclewhen then elsedecode的兩種用法,null

(
  CASE
    WHEN T2.BLESSNUM IS NULL
    THEN 0
    ELSE T2.BLESSNUM

  END) AS BLESSNUM

或者

ENCODE( T2.BLESSNUM, NULL0,T2.BLESSNUM) AS BLESSNUM
ENCODE(t.status,'C','審批通過','P','審批中','N','未提交','D','審批未通過')as status

兩種用法在沒有涉及到的結果通通為null,判斷一個結果值是否為空用is null或者is not null 而不是=null 或者==null

相關文章