Bài học theo mô-đun (4/4)
Nhóm lọc: CÓ
Khi bạn đã có kết quả cho mỗi nhóm (bài trước), bạn thường muốn
chỉ giữ lại các nhóm thỏa mãn một điều kiện: các phòng ban có nhiều hơn
hơn 2 người, các dự án có ngân sách trung bình trên 100 nghìn, người dùng có
ít nhất 10 đơn hàng. Để làm điều này WHERE không đủ.
Tại sao WHERE là không đủ
WHERE lọc tập hợp các hàng trong bảng, trước. Vì vậy nó không thể nhìn thấy
kết quả của COUNT(*) hoặc AVG(...): vào thời điểm WHERE chạy, những kết quả đó
các giá trị chưa được tính toán.
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM employees
WHERE COUNT(*) > 2 -- ❌ doesn't work
GROUP BY department_id;Để lọc sau tổng hợp, có một mệnh đề dành riêng: HAVING.
Cú pháp
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column
HAVING condition_on_aggregate;-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 2;HAVING là của GROUP BY WHERE là của FROM: cùng một ý tưởng
("bộ lọc"), nhưng được áp dụng sau nhóm, trên tổng thể.
Thứ tự logic của các mệnh đề
Để không bao giờ nhầm lẫn giữa WHERE và HAVING nữa, hãy nhớ thứ tự
SQL thực thi chúng một cách tinh thần:
FROM/JOIN— xây dựng bảng bắt đầu bằng cách nối các nguồn.WHERE— bỏ những hàng bạn không quan tâm.GROUP BY— tập hợp các hàng còn lại thành nhóm.HAVING— xóa các nhóm mà bạn không quan tâm.SELECT— tính toán các cột cuối cùng (bao gồm cả tổng hợp).ORDER BY/LIMIT— sắp xếp lại và cắt.
Lưu ý quan trọng:
- trong
WHEREbạn chỉ có thể sử dụng cột bảng; - trong
HAVINGbạn có thể sử dụng nhóm cột và tổng hợp.
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
WHERE e.hired_on >= '2018-01-01' -- filter rows
GROUP BY d.name
HAVING AVG(e.salary) > 35000 -- filter groups
ORDER BY average DESC;Hãy thử nó
Đối với mỗi bộ phận, hiển thị tên (departments.name) và số lượng nhân viên, NHƯNG chỉ dành cho những bộ phận có ít nhất 2 nhân viên. Hai cột, một hàng cho mỗi bộ phận đủ điều kiện.
Hiển thị gợi ý
Điều kiện 'ít nhất 2' trở thành COUNT(*) >= 2 trong HAVING.
Giải pháp khả dụng sau 3 lần thử
Xem lại bài tập
Hiển thị các phòng ban (departments.name) có mức lương trung bình vượt quá 35000. Chỉ xem xét những nhân viên được tuyển dụng từ năm 2018 trở đi. Hai cột: tên và mức trung bình. Sắp xếp theo mức trung bình giảm dần.
Hiển thị gợi ý
WHERE lọc các hàng (nhân viên được tuyển dụng từ năm 2018), HAVING lọc các nhóm (trung bình > 35000).
Giải pháp khả dụng sau 3 lần thử