MySQL CASE WHEN 實際應用(業務實戰)

引言

  非常常見的面試題,也是平時練手的經典題,把知識點串起來的同時也很好的聯繫了業務實際。直接將代碼背誦記憶同樣可在相似場景中發揮作用。

準備 & 用到的知識

  • 年月銷量數據表 sales
  • SQL 編輯器(筆者 dbForge Studio)
  • SQL 基本知識(SELECT, GROUP BY, AS, 聚合函數SUM)

強大的 CASE WHEN 函數,課本少講,十分簡單且實際操作很常用



業務背景

  轉置財務報表,將源數據以更簡潔明瞭的形式呈現給同事、上司,合作伙伴等,以促進後續的數據分析工作。

效果前後
在這裏插入圖片描述
  年份分組,對每一年的各月份的零散銷量進行彙總統計,行轉置成列,打橫輸出,列名剛好對應月份,十分簡潔明瞭


流程分析 & 實現步驟

Step1:思路探索

  需求的實現不一定都是一蹴而就的,先簡單模擬一下低端版本的效果可以爲最終實現打開思路
  代碼拆解:從(FROM) sales 表中讀入數據 --> 按照年月分組(每一年有六個月,1:6 的關係) --> 將分組後的內容呈現(SELECT) 出來,形式爲 年(year_),月(month_),每個月(month_) 對應的總銷量(SUM amount) 的別名(total_amount),
  面試時聊到代碼的閱讀順序的話一上來就說先從 SELECT 開始讀的話會顯得比較沒有經驗,畢竟 SELECT 只是最後的呈現形式。

SELECT
  year_
  , month_  
  /* 這種格式寫代碼比較整潔
     1. 可以直接註釋掉一行而不影響其他行
     2. 可在一行末尾添加註釋而不影響其他行
     3. 可提醒自己不要漏掉括號*/
  , SUM(amount) AS total_amount
FROM
  sales
GROUP BY year_, month_
;

在這裏插入圖片描述
  有點味道了,只不過還暫時是打豎的,顯得比較冗餘(相同的年份和月份都重複出現多次)


Step2:引入 CASE WHEN

  SQL 中每一種函數的妙用都有很多,這裏根據業務需求,有一說一,只分享 CASE WHEN 的冰山一角。
  SQL 的 CASE WHEN 與編程語言中的 if-else 結構非常相似,而該函數又分爲 ‘ 簡單 CASE ’ 與 ‘ 搜索 CASE ’ 兩種,‘ 搜索 CASE‘ 功能更強大(其實也已經包括了簡單 CASE 的內容),通常直接用 ’ 搜索 CASE ‘ 就可以了。
  兩種 CASE 的格式如下:
在這裏插入圖片描述
  搜索表達式之所以叫 “ 搜索 ”,CASE WHEN 後面的表達式可以完全不同,而簡單表達式是 WHEN 後面的表達式可以不同,但 CASE 後面的表達式都是一樣的。記住最後都要 END 結尾,格式也建議稍微注意一下,畢竟一大塊(所以建議只記搜索表達式)

SELECT
  *
  -- 簡單 CASE
  , CASE new_table.total_amount  -- 只能針對一個條件進行
        WHEN 1000 THEN '剛好 1000'  -- 無法設置區間
        WHEN 2000 THEN '剛好 2000'
        ELSE '看着辦'
        END AS '等級'
  -- ============================
  -- 方便得多的搜索 CASE
  , CASE WHEN new_table.total_amount BETWEEN 300 AND 500 THEN '達標'
         WHEN new_table.total_amount BETWEEN 501 AND 600 THEN '銷量不錯'
         WHEN new_table.total_amount > 600 THEN '異常高'
        -- 搜索CASE 還可以同時加上多種類型的判斷條件,即跨列
            -- 這裏垮了 total_amount 和 month 列,簡單 CASE 無法實現
         WHEN new_table.month_ = 1 THEN '新年伊始高低無所謂'
         ELSE '未達標' -- 銷量小於 300 的都算作 ‘未達標’
         END AS '銷量等級'
FROM
  -- 子查詢開始
(
  SELECT
    year_
    , month_  
    , SUM(amount) AS total_amount
  FROM
    sales
  GROUP BY year_, month_
) AS new_table
  -- 子查詢結束(養成良好的標記子查詢開始與結束的習慣)
;

在這裏插入圖片描述
  不要看 CASE WHEN 的語句那麼長,其實也就生成一列而已,長是因爲生成的列中每一行都需要根據需求定製。


Step3:正式組合

  先看首列,只是顯示兩個年份,對 year_ 使用 ’ 搜索 CASE ‘

SELECT
  CASE WHEN year_ = 2018 THEN 2018
       WHEN year_ = 2019 THEN 2019
       END AS Year_
FROM
  sales
GROUP BY year_
;

在這裏插入圖片描述
注意要加上 group by,畢竟屬性 year_ 有重複

  先縮小問題範圍,僅嘗試取出兩年的一月份的對應銷量,再求和。注意敘述順序:取出對應年份的一月份的銷量,再求和。是先取出銷量再求和。
僅需要添加代碼(效果圖在代碼段後)

SUM(CASE WHEN month_ = 1 THEN amount END) AS Jan

在這裏插入圖片描述
  剛纔提到的注意順序問題,即聚合函數 SUM() 需要包裹在最外面,若我們對 THEN 後面的 amount 使用,即 SUM(amount) ,則無法得到我們想要的結果(等下展示)
同理,應用到每一個月中,只是複製粘貼的問題了。

SELECT
  -- year_
  -- , month_
  CASE WHEN year_ = 2018 THEN 2018
       WHEN year_ = 2019 THEN 2019
       END AS Year_
  , SUM(CASE WHEN month_ = 1 THEN amount END) AS Jan
  , SUM(CASE WHEN month_ = 2 THEN amount END) AS Feb
  , SUM(CASE WHEN month_ = 3 THEN amount END) AS Mar
  , SUM(CASE WHEN month_ = 4 THEN amount END) AS Apr
  , SUM(CASE WHEN month_ = 5 THEN amount END) AS May
  , SUM(CASE WHEN month_ = 6 THEN amount END) AS June 
  -- , SUM(amount)
FROM
  sales
GROUP BY year_
;

在這裏插入圖片描述


問題探究

  如果將聚合函數 SUM() 用在了 THEN 後,則會出現如下事與願違的效果

CASE WHEN month_ = 1 THEN SUM(amount) END AS Jan -- 僅對一月份進行嘗試

在這裏插入圖片描述
  一下子就將整一年的銷量都顯示在了一月份。(具體解釋以後再說)



模擬面試

  • 現場寫代碼
  • CASE WHEN 有了解嗎?有幾種 CASE WHEN,說說異同優劣
  • 書寫 CASE WHEN 有什麼值得注意的地方嗎?
  • 談談你對 CASE WHEN 的理解(自己的話敘述執行過程)
  • 你通常都把 CASE WHEN 用到什麼地方?(考察業務背景和知識面)


後記

  SQL 中 CASE WHEN 的作用遠不止於此,還有非常多的騷操作,熟練掌握可大大提高 SQL 取數的工作效率,加油

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章