你有沒有遇過這種情況?
老闆看著報表說:「那個備註欄位一堆空值,看起來好亂,你幫我處理一下。」
聽起來簡單對吧?
用條件判斷不就好了?
但當你真的開始寫,才發現這件事沒有想像中容易。
這篇文章會帶你看看「用條件判斷處理空值」會遇到什麼坑,然後介紹一個超好用的函數:COALESCE(逢空補值)。
用 CASE WHEN 處理空值的困境
前一篇文章我們學過 CASE WHEN 條件判斷,可以根據不同的值回傳不同的結果。
學完之後,你可能會想:「這個好像可以拿來處理空值耶!」
沒錯,你的直覺是對的,條件判斷確實可以用來處理空值。
假設老闆的需求是這樣:
「備註欄位是空值的時候,幫我顯示部門名稱。」
你心想:「這不就是條件判斷嗎?小菜一碟!」
於是你寫出這樣的語法:
CASE 備註
WHEN NULL THEN 部門
END結果發現:不會動。
為什麼?
NULL 不等於 NULL
這裡有個資料庫的重要觀念:NULL 不等於 NULL。
當你寫 WHEN NULL 的時候,其實是在問:「備註 = NULL 嗎?」
但 NULL 代表的是「不知道」、「沒有值」。
兩個「不知道」相比,結果還是「不知道」(也就是 NULL)。
所以 備註 = NULL 的結果永遠是 NULL,不會是 TRUE。
這就是為什麼你的條件判斷沒有作用。
改用 IS NULL 來判斷
既然不能用 = NULL,那就改用 IS NULL:
CASE
WHEN 備註 IS NULL THEN 部門
END看起來對了,但還有問題。
這段程式碼只處理了「備註 IS NULL」的情況。
那當備註「不是」NULL 的時候呢?
你沒有寫 ELSE,所以 CASE WHEN 不知道要回傳什麼。
在 SQL 裡面,當 CASE WHEN 沒有任何條件符合、又沒有寫 ELSE 的時候,預設就會回傳 NULL。
所以結果會變成:
- 備註是 NULL → 回傳部門 ✓
- 備註不是 NULL → 回傳 NULL ✗
原本有值的備註,反而變成 NULL 了!
這顯然不是我們要的結果,所以要把 ELSE 加進去:
CASE
WHEN 備註 IS NULL THEN 部門
ELSE 備註
END這樣就完整了:
- 備註是空值 → 顯示部門
- 備註有值 → 顯示備註
終於搞定!
需求又變了:部門也有空值
正當你鬆一口氣的時候,PM 跑來說:
「老闆說部門那欄也有空值耶,這樣備註是空的時候,顯示出來的部門也是空的,還是很難看,可以處理一下嗎?」
什麼意思?
我們來看看資料:
| 員工 | 備註 | 部門 |
|---|---|---|
| 小明 | 表現優異 | 業務部 |
| 小華 | NULL | 行銷部 |
| 小美 | NULL | NULL |
用剛剛的 CASE WHEN 處理後,結果會變成:
| 員工 | 處理結果(備註欄位) |
|---|---|
| 小明 | 表現優異 |
| 小華 | 行銷部 |
| 小美 | NULL |
小美的備註是 NULL,所以顯示部門。
但問題是,小美的部門也是 NULL!
所以處理完還是 NULL,老闆看了還是不開心。
PM 說:「可以在備註和部門都是空的時候,顯示『未知』嗎?」
也就是說,老闆期望的結果是這樣:
| 員工 | 期望結果(備註欄位) |
|---|---|
| 小明 | 表現優異 |
| 小華 | 行銷部 |
| 小美 | 未知 |
好吧,再改一版。
你開始這樣寫:
CASE
WHEN 備註 IS NULL THEN 部門
WHEN 部門 IS NULL THEN '未知'
ELSE 備註
END這段程式碼的邏輯是:
- 先判斷備註是不是 NULL,是的話就顯示部門
- 再判斷部門是不是 NULL,是的話就顯示「未知」
- 都不符合的話,就顯示備註
看起來合理,但執行後發現:還是有問題。
為什麼?
問題出在 CASE WHEN 的判斷順序。
CASE WHEN 是由上往下判斷的,只要符合某個條件,就會立刻回傳結果,不會再往下判斷。
我們用小美的資料來走一遍:
| 員工 | 備註 | 部門 |
|---|---|---|
| 小美 | NULL | NULL |
- 第一個條件:備註 IS NULL → 小美的備註是 NULL,符合條件!
- 符合條件,立刻回傳「部門」的值
- 小美的部門是 NULL,所以回傳 NULL
- 結束判斷,不會再往下看第二個條件了
你寫的第二個條件 WHEN 部門 IS NULL THEN '未知' 根本沒機會被執行到!
因為小美在第一個條件就被攔截了,直接回傳了部門的值(NULL)。
所以如果兩個欄位都是 NULL,你得到的結果還是 NULL。
終於寫對,但也寫到崩潰
經過一番折騰,你終於寫出正確的版本:
CASE
WHEN 備註 IS NULL AND 部門 IS NOT NULL THEN 部門
WHEN 備註 IS NULL AND 部門 IS NULL THEN '未知'
ELSE 備註
END這段程式碼的邏輯是:
- 當備註是 NULL,而且部門不是 NULL → 顯示部門
- 當備註是 NULL,而且部門也是 NULL → 顯示「未知」
- 都不符合(表示備註有值)→ 顯示備註
關鍵在於:你必須在第一個條件就把「部門是不是 NULL」也考慮進去,用 AND 把兩個條件綁在一起判斷。
這樣才能正確處理所有情況:
- 備註是 NULL、部門有值 → 顯示部門
- 備註是 NULL、部門也是 NULL → 顯示「未知」
- 備註有值 → 顯示備註
但你看看這段程式碼,光處理一個空值就寫了這麼多行。
這真的太痛苦了。
COALESCE 函數:逢空補值的救星
好消息是,SQL 提供了一個專門處理空值的函數:COALESCE。
COALESCE 這個英文單字的意思是「合併」、「匯聚」。
這個名字怎麼來的?
讓我用一個比喻來解釋。
想像你有三張透明圖層,由上往下疊在一起:
- 第一層(最上層):全透明,什麼都沒畫(NULL)
- 第二層(中間層):也是全透明(NULL)
- 第三層(最底層):上面畫了一個紅點
當你把這三張圖層疊在一起,從上往下看,你會看到什麼?
沒錯,就是那個紅點。
因為前兩層是透明的,所以你看穿過去,最後看到的是第三層的紅點。
這就是 COALESCE 的運作邏輯:
它把所有的參數由左到右「疊合」起來,因為 NULL 就像透明的圖層,所以疊合後的結果,就是第一個「看得到」的值。
對應到函數參數的位置:
- 最左邊的參數:最上層,第一優先。只要它有值,後面的都會被「遮住」
- 中間的參數:第二層。只有當前面是 NULL(透明)時,才會被看到
- 最右邊的參數:最底層,通常作為「保底值」。只有當前面全部都是 NULL 時,才會用到它
簡單來說,COALESCE 的功能就是逢空補值:
從左到右檢查每個值,遇到第一個不是 NULL 的值就回傳。
COALESCE 的語法
COALESCE(值1, 值2, 值3, ...)執行邏輯:
- 先看「值1」,如果不是 NULL,就回傳「值1」
- 如果「值1」是 NULL,就看「值2」
- 如果「值2」也是 NULL,就看「值3」
- 一路看下去,直到找到不是 NULL 的值
用 COALESCE 改寫需求
還記得剛剛那個複雜的條件判斷嗎?
CASE
WHEN 備註 IS NULL AND 部門 IS NOT NULL THEN 部門
WHEN 備註 IS NULL AND 部門 IS NULL THEN '未知'
ELSE 備註
END用 COALESCE 只要一行:
COALESCE(備註, 部門, '未知')這行程式碼的意思是:
- 先看「備註」,有值就用它
- 備註是 NULL?那就看「部門」
- 部門也是 NULL?那就顯示「未知」
一行搞定,清楚明瞭。
COALESCE 的實務建議
在實務上使用 COALESCE 時,有一個重要原則:
最後一個值通常放一個「確定不是 NULL」的值。
為什麼?
我們用剛剛的例子來看:
COALESCE(備註, 部門, '未知')這裡最後一個值是字串 '未知',它一定不是 NULL。
這樣不管備註和部門是不是 NULL,最後一定會有一個值回傳,不會出現「全部都是 NULL,結果還是 NULL」的情況。
為什麼要避免結果是 NULL?
因為 NULL 在做運算的時候是「破壞性的存在」。
假設你要計算員工的總獎金:
SELECT 員工, 基本獎金 + 績效獎金 AS 總獎金
FROM 員工表如果某個員工的績效獎金是 NULL,會發生什麼事?
| 員工 | 基本獎金 | 績效獎金 | 總獎金 |
|---|---|---|---|
| 小明 | 1000 | 500 | 1500 |
| 小華 | 1000 | NULL | NULL |
小華的基本獎金明明有 1000 元,但因為績效獎金是 NULL,整個加法的結果就變成 NULL 了!
這就是 NULL 的破壞性:
1000 + NULL= NULLNULL * 5= NULL- 任何數字跟 NULL 做運算,結果都是 NULL
用 COALESCE 保護你的計算
為了避免這種情況,你可以用 COALESCE 把 NULL 補成 0:
SELECT 員工, 基本獎金 + COALESCE(績效獎金, 0) AS 總獎金
FROM 員工表這樣當績效獎金是 NULL 的時候,會自動補成 0,計算就不會被搞砸了:
| 員工 | 基本獎金 | 績效獎金 | 總獎金 |
|---|---|---|---|
| 小明 | 1000 | 500 | 1500 |
| 小華 | 1000 | NULL → 0 | 1000 |
小結
這篇文章學到的重點:
- NULL 不等於 NULL:不能用
= NULL來判斷,要用IS NULL - 用 CASE WHEN 處理空值很麻煩:條件越多,程式碼越複雜
- COALESCE 是逢空補值的最佳解法:從左到右找第一個不是 NULL 的值
- COALESCE 最後一個值要放確定的值:避免整個結果變成 NULL
- NULL 是破壞性的存在:做任何運算前,記得先處理空值
COALESCE 是資料庫中非常重要且常用的函數,一定要學會!