現在是時候深入看看用這些 function 時最常見的錯誤了。就算是很有經驗的 SQL 大神,有時也會踩雷,我們的目標就是學會怎麼發現這些地雷,然後帥氣地閃過去。
你有沒有寫過 query,結果出現很神秘的錯誤訊息,像是 "column must appear in the GROUP BY clause or be used in an aggregate function"?還是查詢結果怪怪的,完全不知道為什麼?這些只是 aggregate function 常見錯誤的冰山一角啦。這堂課就是你的生存指南,帶你在錯誤和誤會的大海裡活下來。
錯誤 1:在 GROUP BY 外用沒 aggregate 的欄位
問題
你寫了一個查詢要回傳 aggregate 資料,但中間加了一個沒在 group 裡、也沒包 aggregate function 的欄位。像這樣:
SELECT 部門, 薪水, SUM(薪水)
FROM 員工
GROUP BY 部門;
PostgreSQL 馬上會跟你說:
ERROR: 欄位 "員工.薪水" 必須出現在 GROUP BY 子句中或被 aggregate function 包住
為什麼會這樣?
當你用 GROUP BY,PostgreSQL 會根據你指定的欄位把資料分組。但如果你又加了一個欄位(這裡是 薪水),PostgreSQL 根本不知道你想幹嘛。你是要一個薪水?平均值?還是別的?它猜不到啦。
怎麼修?有兩種方式:
- 確定所有沒 aggregate 的欄位都在
GROUP BY裡:
SELECT 部門, 薪水
FROM 員工
GROUP BY 部門, 薪水;
- 或者,如果有意義的話,把欄位包進 aggregate function:
SELECT 部門, AVG(薪水) AS 平均薪水
FROM 員工
GROUP BY 部門;
小建議:如果 PostgreSQL 對 GROUP BY 抱怨,問問自己:「這個欄位真的需要嗎?它在查詢裡到底扮演什麼角色?」
錯誤 2:COUNT() 跟 NULL 用錯
問題:你想算有多少員工填了獎金,然後寫:
SELECT COUNT(獎金) AS 獎金數量
FROM 員工;
結果發現數字比你預期的還少。為什麼?因為 COUNT(欄位) 會忽略 欄位 是 NULL 的那幾筆。
解法:如果你想算全部的資料列,就用 COUNT(*):
SELECT COUNT(*) AS 總數量
FROM 員工;
或者你只想算有填獎金的:
SELECT COUNT(獎金) AS 獎金數量
FROM 員工
WHERE 獎金 IS NOT NULL;
小提醒:如果你想分辨有 NULL 的資料和整個表沒資料,記得選對 COUNT(*) 或 COUNT(欄位)。
錯誤 3:忘記用 HAVING 過濾 aggregate,卻用 WHERE
問題:你想找平均薪水超過 5000 的部門。新手可能會這樣寫:
SELECT 部門, AVG(薪水) AS 平均薪水
FROM 員工
WHERE AVG(薪水) > 5000
GROUP BY 部門;
PostgreSQL 會直接報錯:
ERROR: aggregate function 不能用在 WHERE 子句裡
因為 WHERE 是在 分組前 處理的,aggregate function 是 分組後 才算的。所以 AVG(薪水) 在 WHERE 階段還沒出現。
要修正,用 HAVING 來過濾 aggregate 結果:
SELECT 部門, AVG(薪水) AS 平均薪水
FROM 員工
GROUP BY 部門
HAVING AVG(薪水) > 5000;
錯誤 4:WHERE 過濾順序搞混
問題:你想知道每個部門裡,年齡超過 30 歲的員工數。查詢可能長這樣:
SELECT 部門, COUNT(*)
FROM 員工
GROUP BY 部門
WHERE 年齡 > 30;
PostgreSQL 又會抱怨:
ERROR: "WHERE" 附近語法錯誤
為什麼?WHERE 一定要在 GROUP BY 前面。你只是把 WHERE 放錯地方了。
避免這種情況,記得先過濾資料,再分組。
SELECT 部門, COUNT(*)
FROM 員工
WHERE 年齡 > 30
GROUP BY 部門;
錯誤 5:SUM()、AVG() 等 function 遇到 NULL
問題:你想知道發了多少獎金,然後寫:
SELECT SUM(獎金) AS 總獎金
FROM 員工;
結果數字低得很可疑。因為有一半員工沒填獎金,這些 NULL 直接被忽略了。
解法:先把 NULL 換成 0。像這樣:
SELECT SUM(COALESCE(獎金, 0)) AS 總獎金
FROM 員工;
這樣所有 NULL 都會變成 0,總和才會正確。
我們很快就會專門講 COALESCE 這個 function,敬請期待!
錯誤 6:多個 aggregate function 用法沒搞清楚
問題:你想算員工總數和薪水總和。但你寫的查詢結果怪怪的:
SELECT COUNT(薪水) AS 薪水數量, SUM(薪水) AS 薪水總和
FROM 員工;
為什麼會出問題?如果有人薪水是 NULL,COUNT(薪水) 跟 SUM(薪水) 會給你不同的數字,超容易搞混。
記住,aggregate function 是各算各的。有 NULL 就會有不同結果。想要統一,請用 COALESCE 或 COUNT(*):
SELECT COUNT(*) AS 員工總數, SUM(COALESCE(薪水, 0)) AS 薪水總和
FROM 員工;
錯誤 7:GROUP BY 太多欄位,查詢超慢
問題:你下了一個 group 很多欄位的查詢,結果跑了五小時還沒跑完:
SELECT 部門, 職稱, 地點, COUNT(*)
FROM 員工
GROUP BY 部門, 職稱, 地點;
在 group 之前,想想這些欄位真的都需要嗎?group 欄位越多,組合越多,查詢就越慢。如果可以,減少 group 的欄位:
SELECT 部門, COUNT(*)
FROM 員工
GROUP BY 部門;
這些錯誤真的很常見,就算是資深 SQL 工程師也會遇到。希望你現在能更輕鬆閃過這些地雷,寫出又快又正確又漂亮的查詢!
GO TO FULL VERSION