Hãy tưởng tượng bạn đang làm việc với hàng ngàn dòng dữ liệu — làm sao để tìm ra ý nghĩa trong đó? Đây là lúc toán tử GROUP BY xuất hiện — như một nhạc trưởng thực thụ trong dàn nhạc SQL. Nó lấy dữ liệu rời rạc và biến chúng thành một giai điệu rõ ràng: đếm, nhóm, tổng kết. Muốn biết mỗi khách hàng đã đặt bao nhiêu đơn, có bao nhiêu sinh viên ở mỗi khóa học hay lương được phân bổ thế nào theo phòng ban? Tất cả đều là việc của GROUP BY. Hôm nay tụi mình sẽ tìm hiểu cách làm bạn với nó và tận dụng tối đa bảng dữ liệu của bạn nhé.
Nhóm dữ liệu — là quá trình gom các dòng có giá trị giống nhau ở một hoặc nhiều cột thành các nhóm logic. Nó cho phép bạn áp dụng các hàm tổng hợp riêng cho từng nhóm.
Hãy tưởng tượng bạn có bảng nhân viên và muốn biết lương trung bình của từng phòng ban. Một phòng ban — một nhóm. SQL dùng GROUP BY để chia bảng nhân viên thành các nhóm theo phòng ban, rồi áp dụng AVG() cho từng nhóm.
Cú pháp GROUP BY
Quy tắc chính khi dùng nhóm trong SQL: nếu bạn dùng GROUP BY, thì mỗi cột không nằm trong hàm tổng hợp phải được liệt kê trong GROUP BY.
Cú pháp:
SELECT cột1,
hàm_tổng_hợp(cột2)
FROM bảng
GROUP BY cột1;
Các bước thực hiện:
- Chỉ định cột mà bạn muốn nhóm dữ liệu theo trong
GROUP BY. - Dùng các hàm tổng hợp để tính giá trị trong từng nhóm.
- Tất cả các cột trong
SELECTnhưng không nằm trong hàm tổng hợp phải được liệt kê trongGROUP BY. Đúng rồi, SQL khá nghiêm vụ này, quên là nó báo lỗi liền.
Ví dụ: Nhóm sinh viên theo khoa
Giả sử tụi mình có bảng students lưu thông tin sinh viên:
| 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 |
Bây giờ tụi mình muốn biết điểm trung bình (GPA) của từng khoa. Viết query với GROUP BY như sau:
SELECT faculty, AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty;
Kết quả:
| faculty | avg_gpa |
|---|---|
| ComputerSci | 3.9 |
| Math | 3.7 |
| Physics | 3.7 |
SQL đầu tiên chia dữ liệu thành các nhóm theo giá trị cột faculty, rồi áp dụng hàm AVG() cho từng nhóm.
Đặc điểm khi dùng GROUP BY
- Yêu cầu về cột trong
SELECT
SQL yêu cầu tất cả các cột bạn liệt kê trong SELECT nhưng không dùng trong hàm tổng hợp (như SUM(), COUNT()) phải được nhắc đến trong GROUP BY. Vì nếu không nhóm, SQL không biết lấy giá trị nào để hiển thị.
Thử chạy query sau sẽ bị lỗi liền:
SELECT name, AVG(gpa)
FROM students
GROUP BY faculty;
Lỗi: cột name không có trong GROUP BY. Để sửa, thêm name vào GROUP BY:
SELECT name, AVG(gpa)
FROM students
GROUP BY faculty, name;
Nhưng như vậy sẽ nhóm dữ liệu ở mức từng sinh viên — không đúng ý ban đầu tụi mình muốn.
- Nhóm theo nhiều cột
Bạn có thể nhóm dữ liệu không chỉ theo một cột mà còn nhiều cột. Ví dụ, ngoài khoa còn muốn nhóm theo tên sinh viên. Chỉ cần thêm cột thứ hai vào GROUP BY:
SELECT faculty, name, AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty, name;
Bảng gốc:
| 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 |
Kết quả:
| 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 |
- Nhóm với nhiều hàm tổng hợp
Đừng giới hạn mình chỉ một hàm thôi nhé! Ví dụ, muốn đếm số sinh viên ở mỗi khoa và tính điểm trung bình luôn:
SELECT faculty,
COUNT(*) AS student_count,
AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty;
Bảng gốc:
| 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 |
Kết quả:
| faculty | student_count | avg_gpa |
|---|---|---|
| ComputerSci | 2 | 3.9 |
| Math | 2 | 3.7 |
| Physics | 1 | 3.7 |
Đặc điểm nhóm trong SQL: được chọn gì và không được chọn gì
Viết query có GROUP BY thì dễ, nhưng chắc chắn một nửa query của bạn sẽ không chạy được đâu. Nhóm dữ liệu trong SQL hơi khác với cách tụi mình nghĩ trong đầu.
Nếu trong query SQL có GROUP BY, hãy nghĩ tất cả các cột kết quả như là biểu thức tính toán. Cột trong SELECT chỉ có hai loại:
- được tính bằng hàm tổng hợp dựa trên cột của nhóm.
- lấy từ GROUP BY — phải nhóm theo nó.
Nếu bạn chạy query GROUP-BY trên bảng sinh viên, thì bảng kết quả không thể có từng sinh viên cụ thể! Bạn chỉ có thể có chiều cao trung bình, cân nặng trung bình, điểm trung bình. Code kiểu này sẽ không chạy:
SELECT faculty, name
FROM students
GROUP BY faculty;
Thử giải thích tại sao nhé.
Toán tử GROUP BY faculty sẽ chia sinh viên trong bảng students thành các nhóm có cùng faculty ở mỗi nhóm. Vì tất cả sinh viên trong nhóm đều có faculty giống nhau, nên có thể nói thuộc tính faculty là của nhóm sinh viên. Nhưng name thì mỗi sinh viên lại khác nhau. Vậy nên nhóm không có thuộc tính name.
Toán tử GROUP BY faculty, gender sẽ chia sinh viên trong bảng students thành các nhóm có cùng faculty và gender ở mỗi nhóm. Vậy nên tất cả sinh viên trong nhóm đều có faculty và gender giống nhau. Có thể nói nhóm sinh viên có thuộc tính faculty và gender. Nhưng vẫn không có name chung cho nhóm.
Viết như này thì được nè:
SELECT faculty, gender
FROM students
GROUP BY faculty, gender;
Thậm chí như này cũng ok:
SELECT
faculty,
gender,
AVG(age) as group_avg_age, -- Giá trị tính dựa trên age của nhóm sinh viên
MAX(high) as group_high -- Giá trị tính dựa trên high của nhóm sinh viên
FROM students
GROUP BY faculty, gender;
Nhưng chỉ dùng age và high trong SELECT thì không được đâu nhé.
Lỗi thường gặp khi dùng GROUP BY
Khi bạn bắt đầu viết query với GROUP BY, đây là vài "cạm bẫy" có thể gặp phải:
Không liệt kê đủ cột trong
SELECT. Nhớ nha, mỗi cột không phải hàm tổng hợp phải có trongGROUP BY. Không thì SQL không biết hiển thị sao đâu.Nhóm theo
NULL. Giá trịNULLđược coi là một nhóm riêng. Nếu cột của bạn cóNULL, SQL sẽ tạo nhóm choNULLluôn.Nhóm dư thừa. Nếu bạn lỡ thêm quá nhiều cột vào
GROUP BY, kết quả sẽ quá chi tiết và khó phân tích.
Giờ thì bạn đã biết cách nhóm dữ liệu hiệu quả với GROUP BY rồi đó. Đây là một trong những công cụ mạnh nhất trong SQL, giúp bạn dễ dàng làm việc với dữ liệu tổng hợp và tạo báo cáo có cấu trúc. Tiếp theo tụi mình sẽ đào sâu hơn vào "ma thuật" nhóm và tìm hiểu cách lọc thêm với HAVING nhé.
GO TO FULL VERSION