VISEN GROUP
Technology & Engineering

WHERE và HAVING khác nhau thế nào trong SQL?

September 11, 20265 min readUncategorized

Tìm hiểu sự khác biệt giữa HAVING và WHERE trong SQL

Trong SQL, WHEREHAVING đều được dùng để lọc dữ liệu. Vì cùng có nhiệm vụ lọc nên hai mệnh đề này rất dễ bị nhầm lẫn, đặc biệt khi bắt đầu sử dụng GROUP BY và các hàm tổng hợp như COUNT(), SUM() hay AVG().

Điểm khác biệt quan trọng nhất có thể nhớ là:

WHERE lọc từng dòng dữ liệu, còn HAVING lọc các nhóm dữ liệu sau khi GROUP BY.

Để hiểu rõ hơn, hãy cùng sử dụng một bảng orders đơn giản:

idcustomerproductamount
1AnLaptop1000
2AnMouse50
3BìnhLaptop1000
4BìnhKeyboard100
5CườngMouse50

1. WHERE dùng để làm gì?

WHERE được sử dụng để lọc các dòng dữ liệu dựa trên điều kiện cụ thể.

Ví dụ, lấy những đơn hàng có giá trị lớn hơn 100:

SELECT *
FROM orders
WHERE amount > 100;

Kết quả:

idcustomerproductamount
1AnLaptop1000
3BìnhLaptop1000

Ở đây, SQL kiểm tra từng dòng:

  • Đơn hàng 1 → 1000 > 100 → giữ lại
  • Đơn hàng 2 → 50 > 100 → loại
  • Đơn hàng 3 → 1000 > 100 → giữ lại
  • Đơn hàng 4 → 100 > 100 → loại
  • Đơn hàng 5 → 50 > 100 → loại

WHERE đang làm việc với từng row riêng lẻ, chưa có khái niệm về nhóm dữ liệu.


2. HAVING dùng để làm gì?

HAVING được sử dụng để lọc kết quả sau khi dữ liệu đã được nhóm bằng GROUP BY.

Ví dụ, cần tìm những khách hàng có tổng giá trị đơn hàng lớn hơn 1000:

SELECT customer, SUM(amount) AS total_amount
FROM orders
GROUP BY customer
HAVING SUM(amount) > 1000;

Trước tiên, GROUP BY nhóm các đơn hàng theo khách hàng:

customerSUM(amount)
An1050
Bình1100
Cường50

Sau đó HAVING lọc các nhóm:

An     → 1050 > 1000 → giữ
Bình   → 1100 > 1000 → giữ
Cường  → 50 > 1000   → loại

Kết quả cuối cùng:

customertotal_amount
An1050
Bình1100

Điểm quan trọng ở đây là HAVING không còn lọc từng đơn hàng. Nó đang lọc kết quả của từng nhóm khách hàng.


3. Vì sao WHERE và HAVING không thể thay thế cho nhau?

Sự khác biệt này liên quan trực tiếp đến thứ tự xử lý logic của SQL.

Có thể hình dung đơn giản:

FROM
  ↓
WHERE
  ↓
GROUP BY
  ↓
HAVING
  ↓
SELECT
  ↓
ORDER BY

WHERE được xử lý trước GROUP BY, trong khi HAVING được xử lý sau GROUP BY. Vì vậy, tại thời điểm WHERE hoạt động, các giá trị như SUM() hoặc COUNT() theo từng nhóm chưa được tạo ra.

Ví dụ sau là không hợp lệ:

SELECT customer, COUNT(*) AS total_orders
FROM orders
WHERE COUNT(*) > 1
GROUP BY customer;

Lý do là COUNT(*) cần dữ liệu đã được nhóm, nhưng WHERE được xử lý trước GROUP BY.

Cách đúng là:

SELECT customer, COUNT(*) AS total_orders
FROM orders
GROUP BY customer
HAVING COUNT(*) > 1;

Kết quả:

customertotal_orders
An2

4. WHERE và HAVING có thể dùng cùng nhau không?

Có. Đây cũng là trường hợp rất thường gặp trong thực tế.

Ví dụ:

Tìm những khách hàng có các đơn hàng trên 100, sau đó chỉ lấy những khách hàng có tổng giá trị các đơn hàng đó lớn hơn 1000.

Có thể viết:

SELECT customer, SUM(amount) AS total_amount
FROM orders
WHERE amount > 100
GROUP BY customer
HAVING SUM(amount) > 1000;

Có thể hình dung quá trình xử lý như sau:

5 orders
   ↓
WHERE amount > 100
   ↓
2 orders
   ↓
GROUP BY customer
   ↓
2 groups
   ↓
HAVING SUM(amount) > 1000
   ↓
Kết quả cuối cùng

Ở đây:

  • WHERE loại bỏ những đơn hàng không thỏa điều kiện.
  • GROUP BY gom các đơn hàng còn lại theo khách hàng.
  • HAVING tiếp tục loại bỏ những nhóm khách hàng không đạt điều kiện.

Đây chính là lý do WHEREHAVING có thể xuất hiện cùng trong một câu SQL.


5. Một lỗi thường gặp

Một lỗi khá phổ biến là dùng HAVING cho điều kiện không liên quan đến hàm tổng hợp.

Ví dụ:

SELECT customer, COUNT(*) AS total_orders
FROM orders
GROUP BY customer
HAVING customer = 'An';

Câu lệnh này có thể chạy, nhưng nếu mục đích chỉ là lọc khách hàng An, cách hợp lý hơn là:

SELECT customer, COUNT(*) AS total_orders
FROM orders
WHERE customer = 'An'
GROUP BY customer;

Tại sao?

WHERE có thể loại bỏ dữ liệu ngay từ đầu, trước khi GROUP BY thực hiện việc nhóm dữ liệu. Điều này giúp giảm lượng dữ liệu cần xử lý.

Có thể nhớ đơn giản:

Lọc row → WHERE
Lọc group → HAVING


6. WHERE và HAVING khác nhau thế nào?

Tiêu chíWHEREHAVING
Dùng để lọcRowGroup
Thời điểm xử lýTrước GROUP BYSau GROUP BY
Dùng với GROUP BYKhông bắt buộcThường đi cùng
Dùng COUNT(), SUM(), AVG()Không
Mục đích phổ biếnLọc dữ liệu ban đầuLọc kết quả tổng hợp

Một cách nhớ nhanh:

WHERE  → "Dòng nào được giữ lại?"
HAVING → "Nhóm nào được giữ lại?"

7. Khi nào nên dùng WHERE, khi nào nên dùng HAVING?

Bạn có thể tự hỏi một câu rất đơn giản:

Điều kiện đang áp dụng cho từng dòng hay cho kết quả của một nhóm?

Nếu là từng dòng → WHERE

WHERE amount > 100
WHERE customer = 'An'
WHERE product = 'Laptop'

Nếu là kết quả của nhóm → HAVING

HAVING COUNT(*) > 2
HAVING SUM(amount) > 1000
HAVING AVG(amount) > 500

8. Kết luận

WHEREHAVING đều có nhiệm vụ lọc dữ liệu nhưng chúng hoạt động ở hai giai đoạn khác nhau:

WHERE
↓
Lọc từng row
↓
GROUP BY
↓
Tạo các group
↓
HAVING
↓
Lọc các group

Nếu chỉ cần lọc dữ liệu thông thường, hãy nghĩ đến WHERE.

Nếu cần lọc dựa trên kết quả của COUNT(), SUM(), AVG()… sau khi nhóm dữ liệu, hãy nghĩ đến HAVING.

WHERE lọc row — HAVING lọc group.

Đây là nguyên tắc quan trọng nhất cần nhớ khi làm việc với GROUP BY trong SQL.

Leave a Reply

Your email address will not be published. Required fields are marked *