CodeGym /課程 /SQL SELF /使用 aggregate 時常見的錯誤

使用 aggregate 時常見的錯誤

SQL SELF
等級 8 , 課堂 4
開放

現在是時候深入看看用這些 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 根本不知道你想幹嘛。你是要一個薪水?平均值?還是別的?它猜不到啦。

怎麼修?有兩種方式:

  1. 確定所有沒 aggregate 的欄位都在 GROUP BY 裡:
SELECT 部門, 薪水
FROM 員工
GROUP BY 部門, 薪水;
  1. 或者,如果有意義的話,把欄位包進 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 員工;

為什麼會出問題?如果有人薪水是 NULLCOUNT(薪水)SUM(薪水) 會給你不同的數字,超容易搞混。

記住,aggregate function 是各算各的。有 NULL 就會有不同結果。想要統一,請用 COALESCECOUNT(*)

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 工程師也會遇到。希望你現在能更輕鬆閃過這些地雷,寫出又快又正確又漂亮的查詢!

1
問卷/小測驗
資料分組,等級 8,課堂 4
未開放
資料分組
資料分組
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION