WHERE:聚合前過濾資料列,不可使用聚合函數。
HAVING:聚合後過濾分組結果,可使用聚合函數。
| 函數 | 說明 | 忽略 NULL |
|---|---|---|
| AVG | 平均值 | 是 |
| COUNT | 行數/非空值數 | COUNT(*) 不忽略,COUNT(col) 忽略 |
| MAX | 最大值 | 是 |
| MIN | 最小值 | 是 |
| SUM | 總和 | 是 |
GROUP BY 將結果集按指定欄位分組,每組僅輸出一行。SELECT 列表中非分組欄位必須包裹在聚合函數中。
SELECT region, SUM(population), SUM(area) FROM bbc GROUP BY region
→ 依 region 分組,每組輸出 region、人口總和、面積總和。
❌ 錯誤寫法(WHERE 用聚合):
SELECT region, SUM(population), SUM(area) FROM bbc WHERE SUM(population) > 1000000 -- 錯誤:WHERE 階段尚未聚合 GROUP BY region
✅ 正確寫法(HAVING 過濾聚合結果):
SELECT region, SUM(population), SUM(area) FROM bbc GROUP BY region HAVING SUM(population) > 1000000
原因:原始表無單行人口超百萬記錄,必須先分組聚合再過濾。
SELECT region, SUM(population) AS total_pop FROM bbc WHERE area > 1000000 -- 聚合前:先過濾大面積國家 GROUP BY region HAVING SUM(population) > 50000000 -- 聚合後:再過濾大人口地區 ORDER BY total_pop DESC
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
WHERE 在 GROUP BY 前,HAVING 在 GROUP BY 後 —— 這就是能否用聚合函數的根本原因。
WHERE 寫靜態條件(日期範圍、狀態碼),HAVING 寫動態指標(銷售額、筆數、轉換率)。