想像一下你手上有成千上萬筆資料——怎麼從裡面找出重點?這時候 GROUP BY 就像 SQL 裡的指揮家一樣登場啦!它把雜亂的資料變成有節奏的旋律:計算、分組、總結。你想知道每個客戶下了幾個訂單、每個課程有多少學生,還是各部門薪水怎麼分布?這些都靠 GROUP BY。今天我們就來搞懂怎麼跟它變朋友,讓你的資料表發揮最大價值!
分組就是把那些在一個或多個欄位有相同值的資料列合併成邏輯上的群組。這樣你就可以對每個群組分別用聚合函數來計算。
想像你有一張員工表,想知道每個部門的平均薪水。一個部門就是一個群組。SQL 會用 GROUP BY 把員工表依部門分組,然後對每組用 AVG() 算平均薪水。
GROUP BY 的語法
用 SQL 分組最重要的規則:只要你用了 GROUP BY,所有不是聚合函數的欄位都要寫在 GROUP BY 裡。
語法:
SELECT 欄位1,
聚合函數(欄位2)
FROM 資料表
GROUP BY 欄位1;
操作步驟:
- 在
GROUP BY裡指定你想分組的欄位。 - 用聚合函數來計算每個群組的值。
- 所有在
SELECT裡但沒用聚合函數的欄位,都要列在GROUP BY。沒寫 SQL 會直接報錯提醒你。
範例:依學院分組學生
假設我們有一張 students 表,裡面存學生的資料:
| id | name | faculty | gpa |
|---|---|---|---|
| 1 | Alex Lin | ComputerSci | 3.8 |
| 2 | Maria Chi | Math | 3.5 |
| 3 | Anna Song | ComputerSci | 4.0 |
| 4 | Otto Art | Math | 3.9 |
| 5 | Liam Park | Physics | 3.7 |
現在我們想知道每個學院的平均 GPA。這時就要寫個有 GROUP BY 的查詢:
SELECT faculty, AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty;
結果:
| faculty | avg_gpa |
|---|---|
| ComputerSci | 3.9 |
| Math | 3.7 |
| Physics | 3.7 |
SQL 先把資料依 faculty 欄位的值分組,再對每組用 AVG() 算平均。
GROUP BY 的使用細節
SELECT欄位的要求
SQL 規定,只要你在 SELECT 裡寫的欄位沒用聚合函數(像 SUM()、COUNT()),就一定要在 GROUP BY 裡提到。不然 SQL 不知道該怎麼顯示。
你可以試著執行下面這個查詢,會直接報錯:
SELECT name, AVG(gpa)
FROM students
GROUP BY faculty;
錯誤:name 欄位沒寫在 GROUP BY。要修正就把 name 加進 GROUP BY:
SELECT name, AVG(gpa)
FROM students
GROUP BY faculty, name;
但這樣就會分到每個學生一組——跟我們一開始想的不一樣啦。
- 多欄位分組
你可以不只用一個欄位分組,想再加上學生名字也可以。只要在 GROUP BY 裡多加一個欄位:
SELECT faculty, name, AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty, name;
原始表:
| id | name | faculty | gpa |
|---|---|---|---|
| 1 | Alex Lin | ComputerSci | 3.8 |
| 2 | Maria Chi | Math | 3.5 |
| 3 | Anna Song | ComputerSci | 4.0 |
| 4 | Otto Art | Math | 3.9 |
| 5 | Liam Park | Physics | 3.7 |
結果:
| faculty | name | avg_gpa |
|---|---|---|
| ComputerSci | Alex Lin | 3.8 |
| ComputerSci | Anna Song | 4.0 |
| Math | Maria Chi | 3.5 |
| Math | Otto Art | 3.9 |
| Physics | Liam Park | 3.7 |
- 多個聚合函數一起用
不要只用一個函數啦!比如我們想算每個學院有幾個學生,還有平均 GPA:
SELECT faculty,
COUNT(*) AS student_count,
AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty;
原始表:
| id | name | faculty | gpa |
|---|---|---|---|
| 1 | Alex Lin | ComputerSci | 3.8 |
| 2 | Maria Chi | Math | 3.5 |
| 3 | Anna Song | ComputerSci | 4.0 |
| 4 | Otto Art | Math | 3.9 |
| 5 | Liam Park | Physics | 3.7 |
結果:
| faculty | student_count | avg_gpa |
|---|---|---|
| ComputerSci | 2 | 3.9 |
| Math | 2 | 3.7 |
| Physics | 1 | 3.7 |
SQL 分組的細節:哪些可以選、哪些不行
寫分組查詢很簡單,但你大概有一半的查詢一開始都會失敗。分組的邏輯跟我們腦袋裡想的不太一樣。
如果你的 SQL 查詢用了 GROUP BY,就要把結果裡的每個欄位都當成計算出來的東西。SELECT 裡的欄位只能有兩種:
- 用聚合函數算出來的(根據群組裡的欄位)。
- 來自 GROUP BY——就是你分組用的欄位。
如果你對學生表做 GROUP BY 查詢,結果表裡不會有單一學生的資料!你只能有平均身高、平均體重、平均分數。像這樣的 code 就不會動:
SELECT faculty, name
FROM students
GROUP BY faculty;
來看看為什麼。
GROUP BY faculty 會把 students 表依 faculty 分組。每組裡大家的 faculty 都一樣,所以群組有 faculty 這個屬性。但 name 每個學生都不一樣,所以群組沒有 name 這個屬性。
GROUP BY faculty, gender 會把 students 表依 faculty 跟 gender 分組。這樣每組裡大家的 faculty 跟 gender 都一樣,所以群組有這兩個屬性。但還是沒有 name。
這樣寫就可以:
SELECT faculty, gender
FROM students
GROUP BY faculty, gender;
甚至可以這樣:
SELECT
faculty,
gender,
AVG(age) as group_avg_age, -- 這個值是根據群組裡的 age 算出來的
MAX(high) as group_high -- 這個值是根據群組裡的 high 算出來的
FROM students
GROUP BY faculty, gender;
但直接在 SELECT 裡用 age 或 high 是不行的。
用 GROUP BY 常見錯誤
你開始寫 GROUP BY 查詢時,這裡有幾個常見地雷要注意:
SELECT 裡沒寫全欄位。 記得,所有不是聚合的欄位都要寫在
GROUP BY。不然 SQL 不知道怎麼顯示。分組遇到
NULL。NULL會被當成一個獨立的群組。如果你的欄位有NULL,SQL 會幫NULL也分一組。分組太細。 如果你不小心在
GROUP BY裡加太多欄位,結果會變得太細很難分析。
現在你已經知道怎麼用 GROUP BY 有效率地分組資料了。這是 SQL 裡超強大的工具,讓你可以輕鬆處理聚合資料、做出有結構的報表。接下來我們會繼續深入分組的魔法,還有怎麼用 HAVING 加上額外的過濾條件!
GO TO FULL VERSION