1. 程式人生 > 實用技巧 >SQL之case when then用法

SQL之case when then用法

建立表

create table users(id int,name varchar2(20),sex number);
 
insert into users(id,name) values(1,'張一');
insert into users(id,name,sex) values(2,'張二',1);
insert into users(id,name) values(3,'張三');
insert into users(id,name) values(4,'張四');
insert into users(id,name,sex) values(5,'張五',2);
insert into users(id,name,sex) values(6,'張六',1);
insert into users(id,name,sex) values(7,'張七',2);
insert into users(id,name,sex) values(8,'張八',1);
 
commit;

1、上表結果中的"sex"是用程式碼表示的,希望將程式碼用中文表示。可在語句中使用case語句:

select * from users;
select tt.* ,(case tt.sex when 1 then '男'
                      when 2 then '女'
                      else '空的'
                      end
                      )性別
           from users tt ;

2、如果不希望列表中出現"sex"列,語句如下:

select tt.id,tt.name ,(case tt.sex when 1 then '男'
                      when 2 then '女'
                      else '空的'
                      end
                      )性別
           from users tt ;

 

3、將sum與case結合使用,可以實現分段統計。

select sum(case when tt.sex = 1 then 1 else 0 end)男性,
       sum(case  when tt.sex = 2 then 1 else 0 end)女性,
       sum(case when tt.sex <>1 and tt.sex <>1 then 1 else 0 end)性別為空
       from users tt;

        男性         女性       性別為空
---------- ---------- ----------
         3          2          0
       select count(case when tt.sex = 1 then 1  end)男性,
       count(case  when tt.sex = 2 then 1  end)女性,
       count(case when tt.sex <>1 and tt.sex <>1 then 1  end)性別為空
       from users tt;

3.1、這裡發現了一個錯誤 性別為空的為0 why? 不是3嗎?

t-sql 三個用於查詢的篩選器
on 第一個
where 第二個
having 第三個

在SQL中,邏輯表示式的可能值為True False Unknown,稱為三值邏輯
當比較丟失值和另一個值,邏輯結果為Unknown,例如:null>42
所有的篩選器都把Unknown 當做Fasle 處理
但是Check 約束會把Unknown當做True處理
而唯一約束,排序操作和分組操作認為兩個Null值是相等的
如果表中有一列定義了唯一約束,將無法向表內插入該值為Null的兩行
Group by 子句把所有Null值分到一組
Order by 子句把所有Null值排列在一起.


(2)應用ON篩選器(聯接條件) 說到這裡,首先得說下 SQL用於查詢的有三個篩選器,分別是ON,where,having。 這裡的ON篩選器就是用VTB1作為輸入,再利用ON後面的聯結條件進行篩選,生成VTB2。 sql程式設計第二特徵:三值邏輯:它其實就是所謂的TRUE FALSE UNKOWN 主要來說這個UNKOWN 它這邏輯值和NULL在一起就會”出事“。凡是NULL參與的比如 NULL>42, NULL-8>9 這些結果都是UNKOWN UNKOWN 的邏輯結果在不同的環境下是被不同的方式處理的:如 在三個篩選器上,它是會被當做FALSE處理; 在CHECK約束上是會被當成TRUE來處理,check(col>8) 你插入的COL為NULL,因為NULL>8 的結果不就是UNKOWN ,所以是可以插入的。 在篩選器上的2個NULL比較將是FALSE 但是在UNIQUE約束,分組,排序上2個NULL是等價的。  
算術運算
如果算術表示式的任一輸入為空,則該算術表示式(涉及諸如 +、-、* 或 / 的算術運算)結果為空。

例:如果查詢中有一個表示式是r.A + 5, 並且對於關係中某個特定的元組, r.A為空,那麼對此元組來說,該表示式的結果也為空。

比較運算
SQL將涉及空值的任何比較運算的結果視為unknown(既不是謂詞is null,也不是is not null)。unknown是在SQL中除true和false之外的第三個邏輯值。

補充:由於在where子句的謂詞中可以對比較結果使用諸如and、or和not的布林運算,將布林運算擴充套件到可以處理unknown值,運算結果如下:

and:true and unknown = unknown, false and unknown = false, unknown and unknown = unknown
or:true or unknown = true, false or unknown = unknown, unknown or unknown = unknown
not:not unknown = unknown
可以驗證,如果r.A為空,那麼"1 < r.A" 和 "not (1 < r.A)"的結果都為unknown。

"null = null"會返回unknown,而不是true。

 

select  (case when tt.sex <>1 and tt.sex <>2 then 1  end)性別為空
       from users tt;

  

解釋: sex=1 時候 不符合條件 1<>1 ,sex=2 時候 2<>2 不符合條件,為null的時候 unknown 篩選器當做false處理,所以,都不符合條件,不能設定為1,設定為null.

  

這裡就能解釋了

       select  count(case when tt.sex <>1 and tt.sex <>2 then 1  end)性別為空
       from users tt; //結果為0

 解釋: tt.sex <>1 為null<>1 為unkown , unknown and unknown 為unkonwn 被選擇器when 當做fasle處理,被篩下丟棄,所以結果為0

       select  (case when tt.sex <>1 and tt.sex <>2 then 1  end)性別為空
       from users tt;

 所以最後對null的判斷不對,改為:select count(case when tt.sex is null then 1 end)性別為空from users tt;

SqlServer mysql 按月統計所有部門案例:

以訂單統計為例,前端展示柱狀圖(Jquery統計):

表及主要欄位描述如下;表名:Orders
1.日期CreateTime
2.金額Amount
3.使用者UserID

情況一:
根據部門統計某一年每月銷量(查詢一個部門月統計)

1)直接在SQL語句中判斷每月資訊,好處,前臺直接呼叫;壞處,效能不高。

SQL語句:

SELECT 
SUM(CASE WHEN MONTH(s.CreateTime) = 1 THEN s.Amount ELSE 0 END) AS '一月',
SUM(CASE WHEN MONTH(s.CreateTime) = 2 THEN s.Amount ELSE 0 END) AS '二月',
SUM(CASE WHEN MONTH(s.CreateTime) = 3 THEN s.Amount ELSE 0 END) AS '三月',
SUM(CASE WHEN MONTH(s.CreateTime) = 4 THEN s.Amount ELSE 0 END) AS '四月',
SUM(CASE WHEN MONTH(s.CreateTime) = 5 THEN s.Amount ELSE 0 END) AS '五月',
SUM(CASE WHEN MONTH(s.CreateTime) = 6 THEN s.Amount ELSE 0 END) AS '六月',
SUM(CASE WHEN MONTH(s.CreateTime) = 7 THEN s.Amount ELSE 0 END) AS '七月',
SUM(CASE WHEN MONTH(s.CreateTime) = 8 THEN s.Amount ELSE 0 END) AS '八月',
SUM(CASE WHEN MONTH(s.CreateTime) = 9 THEN s.Amount ELSE 0 END) AS '九月',
SUM(CASE WHEN MONTH(s.CreateTime) = 10 THEN s.Amount ELSE 0 END) AS '十月',
SUM(CASE WHEN MONTH(s.CreateTime) = 11 THEN s.Amount ELSE 0 END) AS '十一月',
SUM(CASE WHEN MONTH(s.CreateTime) = 12 THEN s.Amount ELSE 0 END) AS '十二月'
FROM Orders AS s
WHERE YEAR(s.CreateTime) = 2014 

 

一月    二月    三月    四月    五月    六月    七月    八月    九月    十月    十一月    十二月
0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    741327.00    120505.00    0.00

2)統計出資料庫裡有值的月份,再前端邏輯判斷其他月份補0

SQL語句:

SELECT UserID, MONTH(CreateTime) as 月份, SUM(Amount) as 統計
  FROM Orders
 WHERE YEAR(CreateTime) = 2014 -- 這裡假設你要查 2014年的每月的統計。
--其他條件
 GROUP BY UserID, MONTH(CreateTime)

  

參考:https://www.cnblogs.com/qlqwjy/p/7476533.html  

atzhang