Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

SQL SELECT 入門:用 COALESCE 函數處理空值

最後更新:2026年1月26日資料庫

你有沒有遇過這種情況?

老闆看著報表說:「那個備註欄位一堆空值,看起來好亂,你幫我處理一下。」

聽起來簡單對吧?

用條件判斷不就好了?

但當你真的開始寫,才發現這件事沒有想像中容易。

這篇文章會帶你看看「用條件判斷處理空值」會遇到什麼坑,然後介紹一個超好用的函數: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行銷部
小美NULLNULL
備註表現優異
部門業務部
備註NULL
部門行銷部
備註NULL
部門NULL

用剛剛的 CASE WHEN 處理後,結果會變成:

員工處理結果(備註欄位)
小明表現優異
小華行銷部
小美NULL
處理結果(備註欄位)表現優異
處理結果(備註欄位)行銷部
處理結果(備註欄位)NULL

小美的備註是 NULL,所以顯示部門。

但問題是,小美的部門也是 NULL!

所以處理完還是 NULL,老闆看了還是不開心。

PM 說:「可以在備註和部門都是空的時候,顯示『未知』嗎?」

也就是說,老闆期望的結果是這樣:

員工期望結果(備註欄位)
小明表現優異
小華行銷部
小美未知
期望結果(備註欄位)表現優異
期望結果(備註欄位)行銷部
期望結果(備註欄位)未知

好吧,再改一版。

你開始這樣寫:

CASE
    WHEN 備註 IS NULL THEN 部門
    WHEN 部門 IS NULL THEN '未知'
    ELSE 備註
END

這段程式碼的邏輯是:

  1. 先判斷備註是不是 NULL,是的話就顯示部門
  2. 再判斷部門是不是 NULL,是的話就顯示「未知」
  3. 都不符合的話,就顯示備註

看起來合理,但執行後發現:還是有問題。

為什麼?

問題出在 CASE WHEN 的判斷順序。

CASE WHEN 是由上往下判斷的,只要符合某個條件,就會立刻回傳結果,不會再往下判斷。

我們用小美的資料來走一遍:

員工備註部門
小美NULLNULL
備註NULL
部門NULL
  1. 第一個條件:備註 IS NULL → 小美的備註是 NULL,符合條件!
  2. 符合條件,立刻回傳「部門」的值
  3. 小美的部門是 NULL,所以回傳 NULL
  4. 結束判斷,不會再往下看第二個條件了

你寫的第二個條件 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

這段程式碼的邏輯是:

  1. 當備註是 NULL,而且部門不是 NULL → 顯示部門
  2. 當備註是 NULL,而且部門也是 NULL → 顯示「未知」
  3. 都不符合(表示備註有值)→ 顯示備註

關鍵在於:你必須在第一個條件就把「部門是不是 NULL」也考慮進去,用 AND 把兩個條件綁在一起判斷。

這樣才能正確處理所有情況:

  • 備註是 NULL、部門有值 → 顯示部門
  • 備註是 NULL、部門也是 NULL → 顯示「未知」
  • 備註有值 → 顯示備註

但你看看這段程式碼,光處理一個空值就寫了這麼多行。

這真的太痛苦了。

COALESCE 函數:逢空補值的救星

好消息是,SQL 提供了一個專門處理空值的函數:COALESCE。

COALESCE 這個英文單字的意思是「合併」、「匯聚」。

這個名字怎麼來的?

讓我用一個比喻來解釋。

想像你有三張透明圖層,由上往下疊在一起:

  • 第一層(最上層):全透明,什麼都沒畫(NULL)
  • 第二層(中間層):也是全透明(NULL)
  • 第三層(最底層):上面畫了一個紅點

當你把這三張圖層疊在一起,從上往下看,你會看到什麼?

沒錯,就是那個紅點。

因為前兩層是透明的,所以你看穿過去,最後看到的是第三層的紅點。

這就是 COALESCE 的運作邏輯:

它把所有的參數由左到右「疊合」起來,因為 NULL 就像透明的圖層,所以疊合後的結果,就是第一個「看得到」的值。

對應到函數參數的位置:

  • 最左邊的參數:最上層,第一優先。只要它有值,後面的都會被「遮住」
  • 中間的參數:第二層。只有當前面是 NULL(透明)時,才會被看到
  • 最右邊的參數:最底層,通常作為「保底值」。只有當前面全部都是 NULL 時,才會用到它

簡單來說,COALESCE 的功能就是逢空補值:

從左到右檢查每個值,遇到第一個不是 NULL 的值就回傳。

COALESCE 的語法

COALESCE(值1, 值2, 值3, ...)

執行邏輯:

  1. 先看「值1」,如果不是 NULL,就回傳「值1」
  2. 如果「值1」是 NULL,就看「值2」
  3. 如果「值2」也是 NULL,就看「值3」
  4. 一路看下去,直到找到不是 NULL 的值

用 COALESCE 改寫需求

還記得剛剛那個複雜的條件判斷嗎?

CASE
    WHEN 備註 IS NULL AND 部門 IS NOT NULL THEN 部門
    WHEN 備註 IS NULL AND 部門 IS NULL THEN '未知'
    ELSE 備註
END

用 COALESCE 只要一行:

COALESCE(備註, 部門, '未知')

這行程式碼的意思是:

  1. 先看「備註」,有值就用它
  2. 備註是 NULL?那就看「部門」
  3. 部門也是 NULL?那就顯示「未知」

一行搞定,清楚明瞭。

COALESCE 的實務建議

在實務上使用 COALESCE 時,有一個重要原則:

最後一個值通常放一個「確定不是 NULL」的值。

為什麼?

我們用剛剛的例子來看:

COALESCE(備註, 部門, '未知')

這裡最後一個值是字串 '未知',它一定不是 NULL。

這樣不管備註和部門是不是 NULL,最後一定會有一個值回傳,不會出現「全部都是 NULL,結果還是 NULL」的情況。

為什麼要避免結果是 NULL?

因為 NULL 在做運算的時候是「破壞性的存在」。

假設你要計算員工的總獎金:

SELECT 員工, 基本獎金 + 績效獎金 AS 總獎金
FROM 員工表

如果某個員工的績效獎金是 NULL,會發生什麼事?

員工基本獎金績效獎金總獎金
小明10005001500
小華1000NULLNULL
基本獎金1000
績效獎金500
總獎金1500
基本獎金1000
績效獎金NULL
總獎金NULL

小華的基本獎金明明有 1000 元,但因為績效獎金是 NULL,整個加法的結果就變成 NULL 了!

這就是 NULL 的破壞性:

  • 1000 + NULL = NULL
  • NULL * 5 = NULL
  • 任何數字跟 NULL 做運算,結果都是 NULL

用 COALESCE 保護你的計算

為了避免這種情況,你可以用 COALESCE 把 NULL 補成 0:

SELECT 員工, 基本獎金 + COALESCE(績效獎金, 0) AS 總獎金
FROM 員工表

這樣當績效獎金是 NULL 的時候,會自動補成 0,計算就不會被搞砸了:

員工基本獎金績效獎金總獎金
小明10005001500
小華1000NULL → 01000
基本獎金1000
績效獎金500
總獎金1500
基本獎金1000
績效獎金NULL → 0
總獎金1000

小結

這篇文章學到的重點:

  1. NULL 不等於 NULL:不能用 = NULL 來判斷,要用 IS NULL
  2. 用 CASE WHEN 處理空值很麻煩:條件越多,程式碼越複雜
  3. COALESCE 是逢空補值的最佳解法:從左到右找第一個不是 NULL 的值
  4. COALESCE 最後一個值要放確定的值:避免整個結果變成 NULL
  5. NULL 是破壞性的存在:做任何運算前,記得先處理空值

COALESCE 是資料庫中非常重要且常用的函數,一定要學會!

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

資料庫

目錄

  • 用 CASE WHEN 處理空值的困境
  • NULL 不等於 NULL
  • 改用 IS NULL 來判斷
  • 需求又變了:部門也有空值
  • 終於寫對,但也寫到崩潰
  • COALESCE 函數:逢空補值的救星
  • COALESCE 的語法
  • 用 COALESCE 改寫需求
  • COALESCE 的實務建議
  • 為什麼要避免結果是 NULL?
  • 用 COALESCE 保護你的計算
  • 小結