GROUP BY 敘述句 (SQL GROUP BY Statement)
GROUP BY 敘述句用於將查詢結果中特定欄位值相同的記錄分為若干個群組。它通常搭配聚合函數 (Aggregate Functions) 使用,對每個群組分別計算彙總值,而每個群組只會返回一列結果。
若沒有使用 GROUP BY,聚合函數會將整個結果集視為一個群組,只返回單一彙總值。
常用的聚合函數
| 函數 | 說明 |
|---|---|
COUNT() | 計算記錄數量 |
SUM() | 計算數值總和 |
AVG() | 計算平均值 |
MAX() | 找出最大值 |
MIN() | 找出最小值 |
GROUP BY 語法 (Syntax)
SELECT column1, column2, ..., aggregate_function(column)
FROM table_name
[WHERE condition]
GROUP BY column1, column2, ...
[HAVING group_condition]
[ORDER BY column];
重要規則:
SELECT中列出的非聚合欄位,通常都必須出現在GROUP BY子句中。GROUP BY會在WHERE篩選之後、HAVING和ORDER BY之前執行。
GROUP BY 用法範例 (Example)
orders 資料表:
| O_Id | Price | Customer |
|---|---|---|
| 1 | 1000 | 張一 |
| 2 | 2000 | 王二 |
| 3 | 500 | 李三 |
| 4 | 1300 | 張一 |
| 5 | 1800 | 王二 |
範例 1:計算每位顧客的訂單金額總和
SELECT Customer, SUM(Price) AS TotalAmount
FROM orders
GROUP BY Customer;
結果:
| Customer | TotalAmount |
|---|---|
| 張一 | 2300 |
| 王二 | 3800 |
| 李三 | 500 |
Customer 欄位值相同的記錄被分為一組,然後對每組的 Price 欄位加總。
範例 2:計算每位顧客的訂單數量
SELECT Customer, COUNT(*) AS OrderCount
FROM orders
GROUP BY Customer;
結果:
| Customer | OrderCount |
|---|---|
| 張一 | 2 |
| 王二 | 2 |
| 李三 | 1 |
範例 3:搭配 WHERE 條件
先篩選資料,再進行分組:
SELECT Customer, SUM(Price) AS TotalAmount
FROM orders
WHERE Price >= 1000
GROUP BY Customer;
結果:
| Customer | TotalAmount |
|---|---|
| 張一 | 2300 |
| 王二 | 3800 |
李三的訂單金額 500 小於 1000,在 WHERE 階段就被過濾掉了。
多欄位分組
當 GROUP BY 後面指定多個欄位時,只有所有指定欄位的值都相同的記錄才會被分為同一組。
sales 資料表:
| Year | Region | Amount |
|---|---|---|
| 2023 | 北部 | 1000 |
| 2023 | 北部 | 1500 |
| 2023 | 南部 | 800 |
| 2024 | 北部 | 1200 |
| 2024 | 南部 | 900 |
SELECT Year, Region, SUM(Amount) AS TotalSales
FROM sales
GROUP BY Year, Region
ORDER BY Year, Region;
結果:
| Year | Region | TotalSales |
|---|---|---|
| 2023 | 北部 | 2500 |
| 2023 | 南部 | 800 |
| 2024 | 北部 | 1200 |
| 2024 | 南部 | 900 |
GROUP BY 與 NULL 值
GROUP BY 會將所有 NULL 值視為同一組:
SELECT Region, COUNT(*) AS Count
FROM customers
GROUP BY Region;
-- Region 為 NULL 的記錄會被分為一組
GROUP BY 與 DISTINCT 的差異
| GROUP BY | DISTINCT |
|---|---|
| 可搭配聚合函數 | 僅用於去除重複 |
| 返回分組後的彙總結果 | 返回不重複的記錄 |
-- 使用 DISTINCT 取得不重複的客戶
SELECT DISTINCT Customer FROM orders;
-- 使用 GROUP BY 取得每位客戶的統計資訊
SELECT Customer, COUNT(*), SUM(Price) FROM orders GROUP BY Customer;
SQL 執行順序
了解 SQL 的執行順序有助於理解 GROUP BY 的運作:
FROM- 決定資料來源WHERE- 篩選記錄GROUP BY- 將記錄分組HAVING- 篩選分組SELECT- 選取欄位DISTINCT- 去除重複ORDER BY- 排序結果LIMIT/TOP- 限制筆數
GROUP BY 的注意事項
SELECT 欄位必須在 GROUP BY 中
-- 錯誤:O_Id 不在 GROUP BY 中,也不是聚合函數
SELECT Customer, O_Id, SUM(Price)
FROM orders
GROUP BY Customer;
-- 正確
SELECT Customer, SUM(Price)
FROM orders
GROUP BY Customer;
💡 MySQL 的特殊行為: MySQL 在某些模式下允許 SELECT 包含不在 GROUP BY 中的欄位,但這會返回不確定的結果。建議遵循標準 SQL 規範。
搭配 HAVING 篩選分組
HAVING 子句用於篩選分組後的結果:
SELECT Customer, SUM(Price) AS TotalAmount
FROM orders
GROUP BY Customer
HAVING SUM(Price) > 1000;