MySQL Mệnh đề GROUP BY và HAVING kèm ví dụ
⚡ Tóm tắt thông minh
Mệnh đề SQL GROUP BY và HAVING biến các hàng chi tiết thành báo cáo tóm tắt. GROUP BY gộp các hàng có cùng giá trị thành một hàng duy nhất cho mỗi nhóm, trong khi HAVING lọc các nhóm đó sau khi các hàm tổng hợp như COUNT đã được áp dụng.

Mệnh đề GROUP BY trong SQL là gì?
Mệnh đề GROUP BY là một lệnh SQL được sử dụng để nhóm các hàng có cùng giá trịNó được viết bên trong câu lệnh SELECT và thường được sử dụng cùng với các hàm tổng hợp để tạo ra các báo cáo tóm tắt từ cơ sở dữ liệu.
Đó chính là chức năng của nó: nó tóm tắt dữ liệu được lưu trữ trong cơ sở dữ liệu. Các truy vấn chứa mệnh đề GROUP BY được gọi là truy vấn nhóm và chúng trả về một hàng duy nhất cho mỗi mục được nhóm.
NHÓM SQL THEO Cú pháp
Giờ thì mục đích của mệnh đề đã rõ ràng, hãy xem xét cú pháp của một truy vấn nhóm cơ bản.
SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];
tại ĐÂY
- "Câu lệnh SELECT…“là tiêu chuẩn” SQL CHỌN truy vấn lệnh.
- "NHÓM THEO tên_cột1" là mệnh đề thực hiện việc nhóm."ping dựa trên column_name1.
- "[, tên_cột_2, …]” là tùy chọn và đại diện cho các tên cột khác khi nhómping Việc này được thực hiện trên nhiều cột.
- "[ĐANG có điều kiện]Tham số ” là tùy chọn và được sử dụng để giới hạn các hàng bị ảnh hưởng bởi mệnh đề GROUP BY. Nó tương tự như Mệnh đề WHEREngoại trừ việc nó được áp dụng sau nhómping.
Nhómping Sử dụng một cột duy nhất
Cách nhanh nhất để thấy tác dụng của mệnh đề SQL GROUP BY là so sánh một truy vấn không nhóm với một truy vấn có nhóm. Hãy bắt đầu với một truy vấn đơn giản trả về tất cả các mục giới tính trong bảng thành viên.
SELECT `gender` FROM `members`;
| giới |
|---|
| Nữ |
| Nữ |
| Nam |
| Nữ |
| Nam |
| Nam |
| Nam |
| Nam |
| Nam |
Truy vấn trả về chín hàng, và mỗi giá trị đều lặp lại. Giả sử chúng ta muốn các giá trị duy nhất cho giới tính. Truy vấn bên dưới sẽ thêm mệnh đề GROUP BY.
SELECT `gender` FROM `members` GROUP BY `gender`;
Thực thi đoạn script trên trong MySQL Workbench so với myflixdb cung cấp cho chúng ta kết quả sau.
| giới |
|---|
| Nữ |
| Nam |
Lưu ý rằng chỉ có hai hàng được trả về, vì bảng chỉ chứa hai loại giới tính. Mệnh đề GROUP BY đã nhóm tất cả các thành viên "Nam" lại với nhau và trả về một hàng duy nhất cho họ, và nó cũng làm tương tự với các thành viên "Nữ".
Nhómping Sử dụng nhiều cột
Nhómping Việc chỉ sử dụng một cột thường quá sơ sài đối với một báo cáo thực tế. Lệnh GROUP BY chấp nhận một danh sách các cột được phân tách bằng dấu phẩy, và sự kết hợp các giá trị của chúng sẽ xác định từng nhóm.
Giả sử chúng ta muốn có một danh sách các giá trị category_id của phim và năm phát hành tương ứng của các bộ phim đó. Trước tiên, hãy quan sát kết quả của truy vấn đơn giản này.
SELECT `category_id`, `year_released` FROM `movies`;
| Thể loại ID | năm_phát hành |
|---|---|
| 1 | 2011 |
| 2 | 2008 |
| NULL | 2008 |
| NULL | 2010 |
| 8 | 2007 |
| 6 | 2007 |
| 6 | 2007 |
| 8 | 2005 |
| NULL | 2012 |
| 7 | 1920 |
| 8 | NULL |
| 8 | 1920 |
Các hàng được tô sáng cho thấy kết quả chứa các bản ghi trùng lặp. Thực hiện cùng một truy vấn với mệnh đề GROUP BY sẽ loại bỏ chúng.
SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;
Thực thi đoạn script trên trong MySQL Việc chạy lệnh Workbench trên cơ sở dữ liệu myflixdb cho ra các kết quả như hình bên dưới.
| Thể loại ID | năm_phát hành |
|---|---|
| NULL | 2008 |
| NULL | 2010 |
| NULL | 2012 |
| 1 | 2011 |
| 2 | 2008 |
| 6 | 2007 |
| 7 | 1920 |
| 8 | 1920 |
| 8 | 2005 |
| 8 | 2007 |
Mệnh đề GROUP BY hoạt động trên cả category_id và year_released để xác định. độc đáo hàng. Hai hàng trùng lặp cho hạng mục 6 năm 2007 đã được gộp lại thành một.
Quy tắc của ngón tay cái: Nếu mã định danh mục giống nhau nhưng năm phát hành khác nhau, hàng đó được coi là duy nhất. Nếu mã định danh mục và năm phát hành giống nhau ở nhiều hơn một hàng, các hàng đó được coi là trùng lặp và chỉ một trong số chúng được hiển thị.
Nhómping và các hàm tổng hợp
Việc loại bỏ các phần tử trùng lặp rất hữu ích, nhưng sức mạnh thực sự của việc nhóm...ping xuất hiện khi nó được ghép nối với Chức năng tổng hợpHàm tổng hợp tính toán một giá trị cho mỗi nhóm: COUNT đếm số hàng, SUM cộng các giá trị, và AVG, MIN và MAX mô tả độ phân tán.
Giả sử chúng ta muốn tính tổng số thành viên nam và nữ trong cơ sở dữ liệu. Đoạn mã dưới đây sẽ thực hiện điều đó.
SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;
Thực thi đoạn script trên trong MySQL Việc chạy lệnh Workbench trên cơ sở dữ liệu myflixdb cho chúng ta các kết quả sau.
| giới | ĐẾM(`số_thành_viên`) |
|---|---|
| Nữ | 3 |
| Nam | 6 |
Các hàng được nhóm theo từng giá trị giới tính riêng biệt, và số lượng hàng bên trong mỗi nhóm được đếm bằng hàm tổng hợp COUNT. Chín bản ghi thành viên được thu gọn thành hai hàng tóm tắt.
Giới hạn kết quả truy vấn bằng cách sử dụng mệnh đề HAVING
NhómpingKhông phải lúc nào cũng cần điều kiện cho mọi hàng trong bảng. Đôi khi báo cáo phải được giới hạn theo một tiêu chí nhất định, và đó là nhiệm vụ của mệnh đề HAVING.
Giả sử chúng ta muốn biết tất cả các năm phát hành của phim thuộc danh mục có ID 8. Đoạn mã bên dưới sẽ thực hiện điều đó.
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
Thực thi đoạn script trên trong MySQL Việc chạy lệnh Workbench trên cơ sở dữ liệu myflixdb cho ra các kết quả như hình bên dưới.
| id phim | tiêu đề | Giám đốc | năm_phát hành | Thể loại ID |
|---|---|---|---|---|
| 9 | Honey mooners | John Schultz | 2005 | 8 |
| 5 | Những cô gái nhỏ của bố | NULL | 2007 | 8 |
Chỉ những phim có mã số danh mục 8 mới được giữ lại theo điều kiện HAVING.
Cảnh báo: MySQL Từ phiên bản 5.7 trở lên, chế độ ONLY_FULL_GROUP_BY được bật mặc định, và ở chế độ đó, câu lệnh SELECT * với mệnh đề GROUP BY sẽ bị từ chối vì movie_id, title và director không được nhóm hoặc tổng hợp. Trong môi trường sản xuất, hãy đặt tên rõ ràng cho các cột được nhóm, ví dụ: SELECT category_id, year_released FROM movies GROUP BY category_id, year_released HAVING category_id = 8;
WHERE so với HAVING so với GROUP BY so với ORDER BY
Người mới bắt đầu thường nhầm lẫn bốn mệnh đề này, bởi vì tất cả chúng đều hình thành nên tập hợp kết quả. Sự khác biệt nằm ở chỗ khi nào MySQL Cách thức thực hiện như sau: Mệnh đề WHERE chạy trước khi các hàng được nhóm lại, HAVING chạy sau và ORDER BY chạy cuối cùng.
| Khoản | Những gì nó | Khi nó chạy | Chấp nhận các hàm tổng hợp |
|---|---|---|---|
| Ở ĐÂU | Lọc từng hàng riêng lẻ trước khi lọc theo nhóm.ping. | Trước khi nhóm theo | Không |
| NHÓM THEO | Gộp các hàng có cùng giá trị thành một hàng duy nhất cho mỗi nhóm. | Sau WHERE | Không áp dụng |
| ĐANG CÓ | Lọc các nhóm được tạo bởi mệnh đề GROUP BY. | Sau khi nhóm theo | Vâng, ví dụ HAVING COUNT(*) > 2 |
| ĐẶT BỞI | Sắp xếp các hàng còn lại sau khi các điều khoản trước đó được thực thi. | Trang cuối | Vâng, một bí danh tổng hợp có thể được sắp xếp. |
Hậu quả thực tế là về hiệu năng. Việc lọc bằng mệnh đề WHERE loại bỏ các hàng trước khi nhóm được xử lý.ping Công việc bắt đầu, vì vậy một điều kiện không phụ thuộc vào kết quả tổng hợp thì nên dùng mệnh đề WHERE thay vì HAVING.
