SQL Tips 05 – Truy vấn thông tin chưa xảy ra hoặc bị thiếu

Ta thường viết câu lệnh SQL để truy vấn thông tin về những điều đã xảy ra, tuy nhiên đôi khi ta cũng cần lấy thông tin về những gì chưa xảy ra, chưa có. Trong trường hợp này, nhiều người sẽ viết câu lệnh sử dụng toán tử “NOT IN”. Ví dụ dưới đây là câu lệnh sử dụng NOT IN để lấy ra thông tin của những khách hàng mà chưa phát sinh hợp đồng nào với công ty trong năm 2022:


SELECT
	c.CustomerID, c.CustomerName
FROM CUSTOMER AS c
WHERE c.CustomerID NOT IN 
	(SELECT CustomerID FROM CONTRACT WHERE ContractDate BETWEEN '2022-01-01' AND '2022-12-31')

Tuy câu lệnh trên dễ hiểu, nhưng lại tiêu tốn khá nhiều tài nguyên máy tính, vì nó phải quét qua tất cả các CustomerID ở bảng CONTRACT (bao gồm cả các giá trị trùng lặp) để lấy ra kết quả của subquery, rồi so sánh giá trị CustomerID của từng dòng trong bảng CUSTOMER với tập các giá trị của subquery đó.

Để giải quyết vấn đề này, ta có thể sử dụng toán tử “EXISTS”  như trong query dưới đây. Tốc độ xử lý của query sẽ nhanh hơn (đặc biệt là khi subquery trả ra kết quả có rất nhiều dòng) vì khi query engine xử lý và tìm thấy 1 dòng dữ liệu trong subquery thỏa mãn điều kiện, nó sẽ dừng lại và không tiếp tục xử lý subquery nữa.


SELECT
	c.CustomerID, c.CustomerName
FROM CUSTOMER AS c
WHERE NOT EXISTS
	(SELECT * 
	 FROM CONTRACT AS ct
	 WHERE ContractDate BETWEEN '2022-01-01' AND '2022-12-31'
		AND ct.CustomerID = c.CustomerID)

Một cách viết query khác để đạt được kết quả tương tự như trên đó là sử dụng “LEFT JOIN” với điều kiện “WHERE” để trả ra các dòng ở bảng bên trái mà không match được với bảng bên phải:


SELECT
	c.CustomerID, c.CustomerName
FROM CUSTOMER AS c
LEFT JOIN CONTRACT AS ct 
	ON c.CustomerID = ct.CustomerID
	AND ct.ContractDate BETWEEN '2022-01-01' and '2022-12-31'
WHERE ct.CustomerID IS NULL

Giữa 2 cách sử dụng “LEFT JOIN” và “EXISTS”, mỗi hệ quản trị cơ sở dữ liệu (DBMS) lại có cơ chế và những sự ưu tiên khác nhau khi xử lý câu lệnh, vì vậy để chắc chắn cách viết query nào tốt hơn trong 2 cách trên thì ta cần thử nghiệm thực tế.

Add a Comment

Your email address will not be published.