HAVING 篩選 (SQL HAVING)
這篇 SQL HAVING 教學將帶你認識 HAVING 子句的基本概念與用法。HAVING 用來對 GROUP BY 分組後的結果進行條件篩選,通常搭配聚合函數(如 COUNT、SUM、AVG、MIN、MAX)一起使用。
你可能會好奇,WHERE 不是也能篩選資料嗎?沒錯,但 WHERE 是在分組之前篩選個別資料列,而 HAVING 則是在分組之後篩選分組結果。當你需要根據聚合函數的計算結果來篩選時,就必須使用 HAVING。
以下是 WHERE 與 HAVING 的主要差異:
| 比較項目 | WHERE | HAVING |
|---|---|---|
| 篩選時機 | 分組前(GROUP BY 之前) | 分組後(GROUP BY 之後) |
| 篩選對象 | 個別資料列 | 分組後的結果 |
| 能否使用聚合函數 | 不能 | 可以 |
| 常見搭配 | SELECT、UPDATE、DELETE | GROUP BY + 聚合函數 |
HAVING 語法 (SQL HAVING Syntax)
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column_name
HAVING aggregate_function(column_name) condition;
說明:
| 關鍵字 | 說明 |
|---|---|
| SELECT | 指定要查詢的欄位與聚合函數 |
| FROM | 指定資料來源的資料表 |
| WHERE | (選填)在分組前先篩選資料列 |
| GROUP BY | 指定用來分組的欄位 |
| HAVING | 對分組後的聚合結果進行條件篩選 |
HAVING 用法 (Example)
假設我們有一個員工資料表 employees 如下(若需了解如何建立資料表,請參考 CREATE TABLE 教學):
| Name | Department | Salary |
|---|---|---|
| 張一 | 業務部 | 35000 |
| 王二 | 資訊部 | 42000 |
| 李三 | 業務部 | 38000 |
| 趙四 | 資訊部 | 45000 |
| 陳五 | 人資部 | 40000 |
| 林六 | 業務部 | 36000 |
| 黃七 | 資訊部 | 48000 |
篩選員工人數 >= 2 的部門
使用 HAVING 搭配 COUNT() 函數,可以篩選出員工人數大於或等於 2 的部門。
SELECT Department, COUNT(*) AS headcount
FROM employees
GROUP BY Department
HAVING COUNT(*) >= 2;
查詢結果如下:
| Department | headcount |
|---|---|
| 業務部 | 3 |
| 資訊部 | 3 |
因為人資部只有 1 位員工,不符合 COUNT(*) >= 2 的條件,所以被篩選掉了。
篩選平均薪資 >= 40000 的部門
使用 HAVING 搭配 AVG() 函數,可以篩選出平均薪資大於或等於 40000 的部門。
SELECT Department, AVG(Salary) AS avg_salary
FROM employees
GROUP BY Department
HAVING AVG(Salary) >= 40000;
查詢結果如下:
| Department | avg_salary |
|---|---|
| 資訊部 | 45000 |
| 人資部 | 40000 |
篩選薪資總和 > 100000 的部門
使用 HAVING 搭配 SUM() 函數,可以篩選出薪資總和超過 100000 的部門。
SELECT Department, SUM(Salary) AS total_salary
FROM employees
GROUP BY Department
HAVING SUM(Salary) > 100000;
查詢結果如下:
| Department | total_salary |
|---|---|
| 業務部 | 109000 |
| 資訊部 | 135000 |
搭配 WHERE 與 HAVING 一起使用
WHERE 與 HAVING 可以在同一個查詢中同時使用。WHERE 先篩選個別資料列,篩選後的結果再進行 GROUP BY 分組,最後由 HAVING 篩選分組結果。
例如,先排除薪資低於 36000 的員工,再篩選出平均薪資 >= 40000 的部門:
SELECT Department, COUNT(*) AS headcount, AVG(Salary) AS avg_salary
FROM employees
WHERE Salary >= 36000
GROUP BY Department
HAVING AVG(Salary) >= 40000;
查詢結果如下:
| Department | headcount | avg_salary |
|---|---|---|
| 資訊部 | 3 | 45000 |
| 人資部 | 1 | 40000 |
執行順序為:先由 WHERE 排除薪資低於 36000 的張一(業務部,35000),接著 GROUP BY 對剩餘資料進行分組,最後 HAVING 篩選出平均薪資 >= 40000 的部門。業務部因為平均薪資為 37000((38000 + 36000) / 2),不符合條件而被排除。
HAVING 搭配多個條件
HAVING 子句中可以使用 AND、OR 來組合多個條件,就像 WHERE 一樣。
SELECT Department, COUNT(*) AS headcount, AVG(Salary) AS avg_salary
FROM employees
GROUP BY Department
HAVING COUNT(*) >= 2 AND AVG(Salary) >= 40000;
查詢結果如下(只有同時滿足員工人數 >= 2 且平均薪資 >= 40000 的部門):
| Department | headcount | avg_salary |
|---|---|---|
| 資訊部 | 3 | 45000 |
搭配 ORDER BY 排序結果
篩選後的結果可以搭配 ORDER BY 進行排序。完整的查詢語句執行順序為:WHERE → GROUP BY → HAVING → ORDER BY。
SELECT Department, COUNT(*) AS headcount, SUM(Salary) AS total_salary
FROM employees
GROUP BY Department
HAVING COUNT(*) >= 2
ORDER BY total_salary DESC;
查詢結果如下:
| Department | headcount | total_salary |
|---|---|---|
| 資訊部 | 3 | 135000 |
| 業務部 | 3 | 109000 |
SQL 語句執行順序
了解 SQL 語句的執行順序,有助於理解 WHERE 與 HAVING 的差異:
| 順序 | 子句 | 說明 |
|---|---|---|
| 1 | FROM | 指定資料來源 |
| 2 | WHERE | 篩選個別資料列 |
| 3 | GROUP BY | 將資料分組 |
| 4 | HAVING | 篩選分組結果 |
| 5 | SELECT | 選取要顯示的欄位 |
| 6 | ORDER BY | 排序結果 |
從執行順序可以看出,WHERE 在第 2 步執行(分組前),而 HAVING 在第 4 步執行(分組後),這就是為什麼 WHERE 不能使用聚合函數,而 HAVING 可以。
延伸閱讀
- SQL GROUP BY
- SQL 聚合函數
- SQL SELECT
- SQL WHERE
- SQL ORDER BY
- SQL Subquery
- SQL JOIN
- SQL CASE
- SQL DISTINCT
- SQL AS