SQL Server - A CASE Expression Example

在這邊要分享的是一個使用CASE 運算式的題目,題目如下:

假設問題單的處理天數(日曆天)分成最速件1天、速件4天及普通件7天,請列出哪些問題單

的處理已逾期了。

SQL語法使用環境為:SQL Server 2008 R2

TABLE 如下:


欄位說明:

SEQNO - 問題單編號

KIND - 類別。1 => 最速件;2 => 速件;3 => 普通件

CREATEDATE - 填單日期

CLOSEDATE - 結案日期

PS. 實際處理天數 = 結案日期 - 填單日期

首先,我們需要得到的是實際處理天數,才能夠接續由類別種類來判斷哪些已經是逾期了!

1. 得到處理天數

上一篇有提到關於西元年轉換成民國年的方式,這邊題目給我們的是民國年,想當然爾

內建函數是無法讓你直接使用民國年來處理的,因此就摸摸鼻子轉換回來囉!

語法如下:
DATEDIFF(
   D, 
   CAST(
    CAST(SUBSTRING(CREATEDATE,1,3) AS NUMERIC(3)) + 1911 AS VARCHAR(4)
   ) + SUBSTRING(CREATEDATE,4,4), 
   CAST(
    CAST(SUBSTRING(CLOSEDATE,1,3) AS NUMERIC(3))+1911 AS VARCHAR(4)
   ) + SUBSTRING(CLOSEDATE,4,4)
  )

使用內建函數DATEDIFF取得兩個日期間的天數差額,第一個參數D表示以Day來比較,

而第二個參數為得到CREATEDATE的轉換,方式跟轉民國年一樣地土法煉鋼!

2. 加入判斷式得到逾期或未逾期

針對上一個部分得到的實際處理天數,我們現在就可以利用正常SELECT的table來與它

JOIN,如此一來才可以取得實際處理天數的欄位由另一個table來判斷是否已逾期!

語法如下:
SELECT C1.*, C2.PROCESSDAY,
CASE -- 由C2取得實際處理天數,並與C1關連做判斷來得到哪些編號為逾期
  WHEN C1.KIND = '1' AND C2.PROCESSDAY > 1 THEN '逾期' 
  WHEN C1.KIND = '2' AND C2.PROCESSDAY > 4 THEN '逾期'
  WHEN C1.KIND = '3' AND C2.PROCESSDAY > 7 THEN '逾期'
 ELSE '未逾期' 
END AS ISTIMEOUT
FROM CASEDETAIL C1 
JOIN 
( -- 首先取得對應的編號其實際處理的天數
 SELECT SEQNO, CAST(
  DATEDIFF(
   D, 
   CAST(
    CAST(SUBSTRING(CREATEDATE,1,3) AS NUMERIC(3)) + 1911 AS VARCHAR(4)
   ) + SUBSTRING(CREATEDATE,4,4), 
   CAST(
    CAST(SUBSTRING(CLOSEDATE,1,3) AS NUMERIC(3))+1911 AS VARCHAR(4)
   ) + SUBSTRING(CLOSEDATE,4,4)
  ) AS NUMERIC(2)
 ) AS PROCESSDAY 
 FROM CASEDETAIL
) AS C2
ON C1.SEQNO = C2.SEQNO

首先我會將DATEDIFF得到的實際天數做轉換,JOIN的條件很簡單就是兩個table的編號是相

等的,接著使用CASE運算式來判斷C2.PROCESSDAY欄位是否在三種類別的條件下哪些有

逾期。

CASE
      WHEN  條件式  THEN  '滿足印出內容1'
      WHEN  條件式  THEN  '滿足印出內容2'
      ....
      ELSE  '不滿足印出內容'
END AS 此運算式處理的欄位名稱

最後得到的結果如下:


上面得到的處理天數有0天的部分,感覺怪怪的,不過據題目告知

實際處理天數 = 結案日期 - 填單日期

若兩者都在同一天相減確實為0是無疑的!

我想重點在於觀念清楚比較重要,這個部分就以題目給的為主囉!

上面的SQL語法僅供參考,也許還會有更有效率與簡潔的語法囉XD

留言