CodeGym /課程 /SQL SELF /GREATEST() 和 LEAST() 函數還有 NULL

GREATEST() 和 LEAST() 函數還有 NULL

SQL SELF
等級 10, 課堂 2
開放

今天我們要 dive 更細一點的主題:GREATEST() 跟 LEAST() 這兩個函數。你會學到怎麼從多個欄位找出最大值和最小值,還有最重要的,NULL 到底會怎麼影響它們的行為。

如果你曾經在生活中找過什麼最重要的東西(比如愛情、夢想工作或是最強的 pizza 食譜),你應該馬上就能懂 GREATEST() 跟 LEAST() 的用法。這兩個函數就是幫你從一堆 東西 裡面挑出最大或最小的。只是這裡我們不是比 pizza,而是比數字、日期、字串或其他 PostgreSQL 裡的資料。

GREATEST()

GREATEST() 會回傳你給它的參數裡面最大的那個值。

語法:

GREATEST(value1, value2, ..., valueN)

LEAST()

LEAST() 則是反過來:它會找出最小的值。

語法:

LEAST(value1, value2, ..., valueN)

範例:

假設我們有一張 students_scores 表,裡面存著學生三次考試的分數:

student_id exam_1 exam_2 exam_3
1 85 90 82
2 NULL 76 89
3 94 NULL 88

來用一下 GREATEST() 跟 LEAST():

SELECT
    student_id,
    GREATEST(exam_1, exam_2, exam_3) AS highest_score,
    LEAST(exam_1, exam_2, exam_3) AS lowest_score
FROM students_scores;

結果:

student_id highest_score lowest_score
1 90 82
2 89 NULL
3 94 NULL

NULL 怎麼影響 GREATEST() 跟 LEAST()

現在來到最有趣的地方。表格裡除了有數值,也可能有 NULL。 你應該知道 NULL 就是神祕的存在,代表沒資料或不知道的值。 來看看如果 NULL 跑進 GREATEST() 跟 LEAST() 會怎樣。

NULL 的行為:

在 PostgreSQL 裡,GREATEST() 跟 LEAST() 有個特別的行為:它們在找最大或最小值時會 忽略 NULL。 重點: 只有一種情況會回傳 NULL,就是 全部 參數都是 NULL。

範例:

SELECT
    GREATEST(10, 20, NULL, 5) AS greatest_value,
    LEAST(10, 20, NULL, 5) AS least_value;

結果:

greatest_value least_value
20 5

你看,NULL 被直接無視掉,函數只看剩下的 (10, 20, 5) 去找最大最小。

如果全部參數都是 NULL,就會這樣:

範例:

SELECT
    GREATEST(NULL, NULL) AS greatest_nulls,
    LEAST(NULL, NULL) AS least_nulls;

結果:

greatest_nulls least_nulls
NULL NULL

怎麼避免 NULL 帶來的麻煩?

雖然 PostgreSQL 預設會忽略 NULL,但有時你可能想要不一樣的行為。比如你想讓 NULL 當成某個具體的值(像 0 或其他預設值)來算最大/最小。這時就可以用 COALESCE()。

COALESCE(arg1, arg2, ...) 這個函數會回傳第一個不是 NULL 的參數。這樣你就能在丟進 GREATEST() 或 LEAST() 之前,先把 NULL 換成有意義的值。

範例 1:把 NULL 換成 0

假設我們想把沒分數(NULL)當成 0。可以用 COALESCE() 來補預設值。

這是原始表格:

student_id exam_1 exam_2 exam_3
1 90 85 82
2 NULL 89 NULL
3 NULL NULL 94

查詢:

SELECT
    student_id,
    GREATEST(
        COALESCE(exam_1, 0), 
        COALESCE(exam_2, 0), 
        COALESCE(exam_3, 0)
    ) AS highest_score,
    LEAST(
        COALESCE(exam_1, 0), 
        COALESCE(exam_2, 0), 
        COALESCE(exam_3, 0)
    ) AS lowest_score
FROM students_scores;

結果:

student_id highest_score lowest_score
1 90 82
2 89 0
3 94 0

範例 2:把 NULL 換成其他欄位的值

有時候你不想用固定值(像 0),而是想用別的欄位來補。比如 exam_3 沒分數時,就用 exam_1 的分數。

SELECT
    student_id,
    GREATEST(
        exam_1, 
        exam_2, 
        COALESCE(exam_3, exam_1)
    ) AS highest_score
FROM students_scores;

假設我們有這樣的表格:

student_id exam_1 exam_2 exam_3
1 90 85 82
2 NULL 89 NULL
3 70 NULL NULL

查詢結果:

student_id highest_score
1 90
2 89
3 70

實戰案例

案例 1:找出最大折扣

order_id discount_1 discount_2 discount_3
101 5 10 7
102 NULL 3 8
103 15 NULL NULL
104 NULL NULL NULL

你現在在處理 orders 這張表,每個訂單可能有三種不同的折扣。你要找出每個訂單裡最大的那個折扣。

SELECT
    order_id,
    GREATEST(discount_1, discount_2, discount_3) AS max_discount
FROM orders;

結果:

order_id max_discount
101 10
102 8
103 15
104 NULL

案例 2:找出商品最低價

在 products 表裡,每個商品有三種貨幣的價格(USD, EUR, GBP)。你的任務是找出每個商品的最低價。

product_id price_usd price_eur price_gbp
1 100 95 80
2 NULL 150 140
3 200 NULL NULL
4 NULL NULL NULL
SELECT
    product_id,
    LEAST(price_usd, price_eur, price_gbp) AS lowest_price
FROM products;
product_id lowest_price
1 80
2 140
3 200
4 NULL

如果全部價格都是 NULL,結果也會是 NULL

用 GREATEST() 跟 LEAST() 常見錯誤

錯誤 1:因為 NULL 得到意外的結果。

我們前面有講過 NULL 在 PostgreSQL 裡對 GREATEST() 跟 LEAST() 的影響。常見的錯誤是,有些人習慣其他資料庫系統的 NULL 行為(只要有一個 NULL 就整個結果都是 NULL),所以以為 PostgreSQL 也會這樣。

錯誤怎麼發生: 你可能會以為只要參數裡有 NULL,函數就一定會回傳 NULL。結果你會不必要地對所有參數都用 COALESCE(),這樣反而讓查詢變複雜又慢,尤其如果你本來就想讓 NULL 被忽略。

錯誤 2:用 GREATEST() 跟 LEAST() 比不同型別的值。

GREATEST() 跟 LEAST() 設計來比同一種 資料型別 的值,或是可以自動轉換的型別。如果你硬要比完全不相容的型別,會直接報錯。

錯誤怎麼發生: 你會收到一個錯誤訊息,說資料型別不相容。

2
任務
SQL SELF, 等級 10, 課堂 2
上鎖
使用 `GREATEST()` 和 `LEAST()`
使用 `GREATEST()` 和 `LEAST()`
2
任務
SQL SELF, 等級 10, 課堂 2
上鎖
使用 `COALESCE()` 搭配 `GREATEST()` 和 `LEAST()`
使用 `COALESCE()` 搭配 `GREATEST()` 和 `LEAST()`
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION