Chuyển đến nội dung chính

Sự khác biệt giữa WHERE và HAVING trong SQL

Tìm hiểu cách WHERE lọc dữ liệu cấp hàng trong truy vấn SQL, trong khi HAVING lọc dữ liệu đã nhóm sau khi tổng hợp, và nắm vững cách dùng riêng của chúng trong truy vấn SQL.
Đã cập nhật 5 thg 6, 2026  · 8 phút đọc

WHEREHAVING là hai mệnh đề thiết yếu trong SQL. Dù bạn viết truy vấn siêu nâng cao hay rất đơn giản, bạn sẽ gặp nhu cầu dùng cả hai. Bạn có thể coi WHEREHAVING như anh em. Chúng cùng phục vụ một chức năng tương tự (lọc), và thường xuất hiện cùng nhau. Nhưng giống như anh em, chúng có đặc điểm riêng và vai trò khác biệt. 

Nếu bạn đang tìm cách phân biệt WHEREHAVING, tôi gợi ý đăng ký lộ trình kỹ năng SQL Fundamentals của chúng tôi như một điểm khởi đầu tốt và toàn diện. Khóa học sẽ dạy bạn về các mệnh đề SQL khác nhau, thứ tự thực thi của SQL, tối ưu hóa truy vấn SQL, và nhiều điều quan trọng khác.  

Câu trả lời ngắn: WHERE so với HAVING 

Câu trả lời ngắn gọn và cũng là nguồn gây nhầm lẫn cho nhiều người là WHERE hoạt động trên dữ liệu cấp hàng, còn HAVING vận hành trên dữ liệu đã được nhóm. Dưới đây là hướng dẫn:

  • WHERE lọc các hàng trước khi có bất kỳ thao tác nhóm hoặc tổng hợp nào. Nó áp dụng cho từng hàng riêng lẻ và không thể dùng với các hàm tổng hợp.

  • HAVING lọc các nhóm sau khi việc nhóm và tổng hợp đã được thực hiện. Nó áp dụng cho kết quả của các hàm tổng hợp và dùng kết hợp với GROUP BY.

Ví dụ nhanh để minh họa sự khác biệt 

Hãy xem một ví dụ nhanh. Nếu bạn muốn tự thực hành, bạn có thể tải bộ dữ liệu cho thuê bất động sản từ kho GitHub này.

Giờ giả sử chúng ta cần trả về tất cả bất động sản trong bộ dữ liệu có giá thuê dưới $500. Mức chi tiết của mỗi hàng trong bộ dữ liệu (một bất động sản mỗi hàng) khớp với mức chi tiết của điều kiện truy vấn. Do đó, chúng ta dùng WHERE trong truy vấn sau:

SELECT *
FROM rentals
WHERE rental_price < 500

Kết quả sẽ trông như thế này. Lưu ý có 118 hàng được trả về.

Lọc hàng đơn giản với SQL WHERE

Lọc hàng đơn giản với WHERE. Ảnh: Tác giả.

Giờ giả sử chúng ta không muốn có bảng liệt kê bất động sản, mà là các thành phố có giá thuê trung bình dưới $2.700. Thay vì mỗi hàng tương ứng một bất động sản, chúng ta sẽ nhóm các hàng và tổng hợp giá thuê thành giá thuê trung bình cho mỗi thành phố. Vì vậy, chúng ta sẽ dùng HAVING, như trong truy vấn này:

SELECT city, AVG(rental_price) AS average_rent
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;

Và kết quả sẽ là như thế này. Lưu ý chỉ có một kết quả. 

Lọc nhóm đơn giản với SQL HAVING

Lọc nhóm đơn giản với HAVING. Ảnh: Tác giả.

WHERE, HAVING và thứ tự thực thi trong SQL

Chúng ta thấy WHERE dùng để lọc ở cấp độ hàng, trong khi HAVING lọc ở cấp độ tổng hợp. Hiểu sự khác biệt này cũng mở đường để chúng ta tìm hiểu về thứ tự thực thi các mệnh đề của SQL

WHERE được đánh giá trước GROUP BY, và ngay sau FROM (và JOIN nếu có); nó không thể xử lý bất kỳ thao tác nhóm hay tổng hợp nào. WHERE được áp dụng trước khi thực hiện tổng hợp. Đó là lý do nó chỉ hoạt động trên dữ liệu cấp hàng. 

Trong khi đó, HAVING đến sau khi thực thi mệnh đề GROUP BY. Điều này có nghĩa nó được áp dụng sau khi đã biến đổi bảng và nhóm dữ liệu ở một mức khác với mức chi tiết của bảng nguồn. HAVING hoạt động trên phiên bản bảng mới đã được biến đổi. 

Cách sử dụng mệnh đề WHERE trong SQL

Hãy lùi lại một bước và xem từng mệnh đề riêng lẻ. Ta có thể bắt đầu với mệnh đề WHERE.

Cú pháp và câu lệnh WHERE

WHERE có thể dùng trong ba loại câu lệnh SQL: SELECT, UPDATEDELETE.

WHERE trong câu lệnh SELECT

Trong các câu lệnh SELECT, là những câu lệnh dùng để truy xuất dữ liệu từ cơ sở dữ liệu, WHERE đóng vai trò trực tiếp trong việc lọc ở cấp độ hàng và có vị trí quen thuộc ngay sau mệnh đề FROM, như ta thấy trong truy vấn sau:

SELECT column1, column2… etc.
FROM table_name
WHERE condition;

WHERE dùng với SELECT là nơi mà mệnh đề WHERE thường hay bị nhầm với HAVING

WHERE trong câu lệnh UPDATE

Ngoài ra, WHERE đóng vai trò quan trọng trong câu lệnh UPDATE để xác định đúng hàng cần cập nhật dữ liệu, như trong cú pháp sau:

UPDATE table_name
SET column_name1 = value1, column_name2 = value2… etc.
WHERE condition;

WHERE trong câu lệnh DELETE

WHERE cũng rất hữu ích trong các câu lệnh DELETE để xác định bản ghi (hàng) cần xóa, như ta thấy ở đây:

DELETE FROM table_name
WHERE condition;

Cách viết điều kiện WHERE

Các điều kiện WHERE được viết dưới dạng biểu thức logic đơn giản. Nó gồm ba phần: biến/toán hạng, điều kiện và giá trị/kết quả. Hãy xem các lựa chọn cho điều kiện WHERE bao gồm cả toán tử so sánh và toán tử logic.  

Ký hiệu toán tử Mô tả Kiểu dữ liệu toán hạng
= Bằng (đúng ngày) Số, Văn bản, Ngày/dấu thời gian, Boolean
< Nhỏ hơn (trước ngày) Số, Ngày/dấu thời gian
> Lớn hơn (sau ngày) Số, Ngày/dấu thời gian
<= Nhỏ hơn hoặc bằng (đúng ngày hoặc trước) Số, Ngày/dấu thời gian
>= Lớn hơn hoặc bằng (đúng ngày hoặc sau) Số, Ngày/dấu thời gian
<> (!=) Khác (không đúng ngày) Số, Văn bản, Ngày/dấu thời gian, Boolean
IN Bằng một trong nhiều giá trị (trên nhiều ngày) Số, Văn bản, Ngày/dấu thời gian, Boolean (dù không hợp lý!)
LIKE Khớp mẫu văn bản (dùng ký tự đại diện) Văn bản
BETWEEN Tồn tại trong một khoảng Số, Ngày/dấu thời gian
AND Kết hợp nhiều điều kiện, tất cả phải đúng Logic (Boolean)
OR Kết hợp nhiều điều kiện, ít nhất một điều kiện đúng Logic (Boolean)
NOT Phủ định một điều kiện Logic (Boolean)
IS NULL Kiểm tra giá trị null Mọi kiểu dữ liệu
IS NOT NULL Kiểm tra giá trị không null Mọi kiểu dữ liệu

Dưới đây là một ví dụ dùng NOT cùng với toán tử so sánh IN:

SELECT *
FROM rentals
WHERE city NOT IN ('Cairo', 'Giza');

Câu lệnh sẽ trả về tất cả bất động sản không thuộc các thành phố Cairo hoặc Giza.

Sử dụng NOT với WHERE

Bất động sản ngoài Cairo và Giza. Ảnh: Tác giả.

Các trường hợp sử dụng WHERE

Biết rằng WHERE hoạt động với các câu lệnh SELECT, UPDATEDELETE, ta có thể dự đoán ba trường hợp sử dụng: lọc cấp hàng, truy xuất dữ liệu và thao tác dữ liệu.

Lọc cấp hàng

Chúng ta có thể lọc các hàng trong bảng dựa trên một hoặc nhiều điều kiện. Truy vấn sau lọc các hàng để chỉ bao gồm bất động sản kiểu villa.

SELECT *
FROM rentals
WHERE type = ‘villa’;

Sử dụng NOT với WHERE

Chọn bất động sản kiểu villa. Ảnh: Tác giả.

Truy xuất dữ liệu

WHERE có thể dùng để truy xuất một điểm dữ liệu cụ thể mà chúng ta cần. Điều này tương tự lọc cấp hàng nhưng cụ thể hơn. Giả sử chúng ta cần biết ID của bất động sản có sẵn vào ngày 1 tháng 1 năm 2022 tại Cairo, có thể dùng truy vấn sau:

SELECT property_id
FROM rentals
WHERE available_date = '2022-01-01'
AND city = 'Cairo';

Lọc cấp hàng với WHERE

Truy xuất một điểm dữ liệu. Ảnh: Tác giả.

Thao tác dữ liệu

Cuối cùng, WHERE là trợ thủ đắc lực để chỉnh sửa giá trị và xóa bản ghi cụ thể trong cơ sở dữ liệu. Ví dụ, giả sử chúng ta phát hiện bất động sản 171 thực ra không thân thiện với thú cưng, ta có thể sửa cột pet_friendly bằng WHERE trong câu lệnh UPDATE như sau:

UPDATE rentals
SET pet_friendly = false
WHERE property_id = 171;

Cách sử dụng mệnh đề HAVING trong SQL

Giờ là lúc chuyển sang mệnh đề HAVING với cùng mức độ chi tiết. 

Cú pháp và câu lệnh HAVING

Trước hết, cần biết mệnh đề HAVING chỉ có thể dùng trong câu lệnh SELECT. Do đó, cú pháp duy nhất của nó như sau:

SELECT grouped_column, aggregate_function(aggregated_column)… etc.
FROM table_name
GROUP BY grouped_column
HAVING condition

Lưu ý bạn có thể thêm nhiều cột nhóm và nhiều cột tổng hợp. Chúng ta sẽ xem ví dụ bên dưới.

Cách viết điều kiện HAVING

Giống WHERE, các điều kiện HAVING được viết như các biểu thức logic nhưng có thêm một thành phần là hàm tổng hợp. Vì vậy, một điều kiện HAVING gồm: 1) Hàm tổng hợp, 2) biến/toán hạng, 3) Toán tử so sánh, và 4) giá trị/kết quả.

Các hàm tổng hợp với HAVING

SQL chủ yếu có năm hàm tổng hợp, cộng thêm một hàm thứ sáu thuộc trường hợp đặc biệt. Các hàm này là:

Hàm tổng hợp Kiểu dữ liệu phù hợp
SUM() Số
AVG() Số
MIN() Số, Văn bản, Ngày/dấu thời gian
MAX() Số, Văn bản, Ngày/dấu thời gian
COUNT() Số, Văn bản, Ngày/dấu thời gian, Boolean

Hãy thử một ví dụ. Ở đây, chúng ta dùng hàm COUNT() với GROUP BY để tạo bảng tần suất, và dùng điều kiện HAVING làm bộ lọc. Cụ thể, chúng ta cần biết các thành phố được nhắc đến 150 lần trở xuống, trong ngữ cảnh này liên quan đến số lượt đăng ký. Có thể dùng truy vấn này:

SELECT city, COUNT(*) AS properties_count
FROM rentals
GROUP BY city
HAVING COUNT(*) <= 150;

Sử dụng MAX() với HAVING

Sử dụng COUNT() với HAVING. Ảnh: Tác giả.

Toán tử so sánh và logic

HAVING chấp nhận tất cả các toán tử so sánh và logic mà WHERE chấp nhận. Điểm khác biệt duy nhất là kiểu dữ liệu phù hợp với HAVING trước hết phụ thuộc vào hàm tổng hợp, như ta thấy trong bảng ở trên.

Các trường hợp sử dụng HAVING

Không giống WHERE, HAVING không thể dùng trong các câu lệnh UPDATEDELETE; HAVING chỉ dùng để truy xuất dữ liệu. Nói chung, điều này tương ứng với hai kịch bản:

Lọc cấp nhóm

Đây là cách dùng phổ biến và bình thường của HAVING. Một ví dụ là chỉ trả về các thành phố có giá thuê trung bình dưới $2.700.

SELECT city, AVG(rental_price) AS avg_price
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;

Lọc một hàng

Đây là trường hợp không phổ biến, nhưng HAVING có thể dùng để trả về một phép tổng hợp một hàng, như một chỉ số hay KPI, chỉ khi nó thỏa điều kiện nhất định. Có thể đạt được điều này bằng cách dùng HAVING mà không cần GROUP BY. Trong ví dụ sau, chúng ta trả về giá thuê trung bình chỉ khi nó dưới $2.800. Nếu thước đo thỏa điều kiện, chúng ta sẽ có một kết quả một hàng. Nếu không, bảng sẽ rỗng.

SELECT AVG(rental_price) as avg_price
FROM rentals
HAVING AVG(rental_price) > 2800;

Kết hợp WHERE và HAVING

WHEREHAVING có thể kết hợp để lọc bảng cả trước và sau khi tổng hợp. Trong ví dụ sau, chúng ta trả về số bất động sản ở mỗi thành phố, chỉ tính các bất động sản thân thiện với thú cưng, và lọc chỉ các thành phố có hơn 80 bất động sản.

SELECT city, COUNT(*) AS number_properties
FROM rentals
WHERE pet_friendly = true
GROUP BY city
HAVING COUNT(*) > 80;

Kết hợp WHERE với HAVING

Kết hợp cơ bản giữa WHERE và HAVING. Ảnh: Tác giả.

Sự khác biệt về hiệu năng giữa WHERE và HAVING

Chúng ta biết mệnh đề WHERE được áp dụng trước khi nhóm hoặc tổng hợp. Cũng vì lý do đó, do nó giảm số lượng hàng được xử lý ngay từ đầu truy vấn, WHERE hiệu quả hơn cho việc lọc từng hàng. 

Mặt khác, chúng ta biết mệnh đề HAVING được áp dụng sau khi tổng hợp và lọc tập kết quả dựa trên dữ liệu đã nhóm. Vì lý do này, do nó xử lý dữ liệu sau khi tất cả các hàng đã được nhóm, nó thường kém hiệu quả hơn WHERE, dù vẫn cần thiết cho các điều kiện liên quan đến hàm tổng hợp.

Hãy xem truy vấn này:

SELECT city, COUNT(*)
FROM rentals
GROUP BY city
HAVING rental_price < 2700;

Truy vấn này không hiệu quả vì điều kiện rental_price không phụ thuộc vào bất kỳ phép tổng hợp nào — nó lọc các hàng riêng lẻ. Truy vấn sẽ nhóm tất cả các bản ghi thuê theo thành phố, đếm chúng, và sau đó mới lọc kết quả, điều này kém hiệu quả vì xử lý các hàng không cần thiết. Vì vậy, truy vấn sau sẽ nhanh hơn:

SELECT city, COUNT(*)
FROM rentals
WHERE rental_price < 2700
GROUP BY city;

Mẹo tối ưu WHERE và HAVING

Dựa trên những điều trên, chúng ta có thể rút ra một số thực hành tốt giúp tối ưu việc dùng các mệnh đề WHEREHAVING. Điều này quan trọng nếu bạn có bộ dữ liệu lớn.

  1. Lọc thật chọn lọc: Chỉ lọc đúng những giá trị bạn cần và không hơn. Điều này sẽ giúp giảm số hàng trong tập xem, từ đó nâng cao hiệu quả truy vấn.

  2. Giữ đơn giản: Loại bỏ các điều kiện, phép tổng hợp và ép kiểu không cần thiết. Tất cả những phần dư thừa này đều phải trả giá về tính toán.

  3. Lọc sớm: Nếu bạn thực hiện tổng hợp ở cấp nhóm, hãy tiền lọc các hàng bằng WHERE để tăng tốc quá trình nhóm. Làm vậy sẽ giảm số hàng cần xử lý khi nhóm.

Bảng so sánh

Hãy tóm tắt ý chính trong một bảng tiện lợi:

So sánh WHERE HAVING
Mục đích chính Lọc ở cấp độ hàng Lọc ở cấp độ nhóm
Cú pháp cơ bản SELECT column1, column2... FROM table_name WHERE condition; SELECT grouped_column, aggregate_function(aggregated_column)... FROM table_name GROUP BY grouped_column HAVING condition;
Thứ tự đánh giá Trước GROUP BY Sau GROUP BY
Câu lệnh tương thích SELECT, UPDATE, DELETE  SELECT
Điều kiện Không thể bao gồm hàm tổng hợp Phải bao gồm hàm tổng hợp
Trường hợp sử dụng Lọc cấp hàng Truy xuất dữ liệu Thao tác dữ liệu Lọc cấp nhóm Lọc một hàng
Truy vấn lồng Có thể dùng với truy vấn lồng Phải viết dưới dạng CTE

Kết luận

Xuyên suốt bài viết, chúng ta đã khám phá sự khác biệt chính giữa WHEREHAVING trong SQL, đó là WHERE lọc các hàng trước khi tổng hợp, còn HAVING lọc dữ liệu đã nhóm sau khi tổng hợp. Chúng ta cũng đề cập một số khác biệt ít được biết đến hơn, như việc WHERE có thể dùng với các câu lệnh SELECT, UPDATEDELETE, còn HAVING chỉ dùng với SELECT. Chúng ta cũng bàn đôi chút về hiệu năng.

SQL Basics Cheat Sheet của DataCamp cung cấp phần tổng kết hay về các mệnh đề WHEREHAVING, cùng một số hướng dẫn về cách lọc trong SQL. Ngoài ra, nếu bạn mới bắt đầu với SQL, bạn sẽ muốn xem lộ trình kỹ năng SQL Fundamentals và lộ trình nghề nghiệp Associate Data Analyst in SQL


Islam Salahuddin's photo
Author
Islam Salahuddin

Islam là một tư vấn dữ liệu tại The KPI Institute. Xuất thân từ ngành báo chí, Islam có nhiều mối quan tâm đa dạng, bao gồm viết lách, triết học, truyền thông, công nghệ và văn hóa.

Câu hỏi thường gặp

Sự khác biệt giữa WHERE và HAVING là gì?

WHERE thực hiện lọc ở cấp độ hàng, còn HAVING thực hiện lọc ở cấp độ nhóm.

Tôi có thể kết hợp WHERE và HAVING trong một truy vấn không?

Có, và rất khuyến khích dùng WHERE nếu bạn sẽ dùng HAVING.

WHERE có thể làm việc với các hàm tổng hợp như HAVING không?

Không, chỉ HAVING mới có thể làm việc với các hàm tổng hợp.

WHERE và HAVING có dùng cùng các toán tử so sánh và logic không?

Có, cả hai cùng hoạt động với các toán tử giống nhau vì điều kiện WHEREHAVING được viết dưới dạng biểu thức logic.

Tôi có thể dùng HAVING mà không có GROUP BY không?

HAVING thường được dùng sau khi nhóm với GROUP BY. Ngoại lệ duy nhất là lọc dạng một giá trị (như tính một chỉ số).

Chủ đề

Học SQL với DataCamp

Courses

Xử lý dữ liệu trong SQL

4 giờ
323.5K
Xem chi tiếtRight Arrow
Bắt đầu khóa học
Xem thêmRight Arrow