SQL Tips 08 – Filter chính xác vế bên phải của câu lệnh Left Join

Giả sử bạn phải viết 1 query để lấy ra dữ liệu của tất cả các khách hàng của doanh nghiệp của bạn, và với những khách hàng nào có phát sinh hợp đồng với doanh nghiệp trong năm 2022 thì cần thể hiện ra những hợp đồng đó.

Với đề bài như vậy, có những bạn sẽ viết query như sau:


SELECT 
	cust.CustomerID, 
	cust.CustomerName, 
	con.ContractNumber, 
	con.ContractDate, 
	con.ContractAmount
FROM Customers AS cust
LEFT JOIN Contracts AS con
	ON cust.CustomerID = con.CustomerID
WHERE con.ContractDate BETWEEN CAST('2022-01-01' AS DATE)
	AND CAST('2022-12-31' AS DATE);

Query này chưa đáp ứng được yêu cầu của đề bài vì bạn sẽ thấy là kết quả trả ra không bao gồm đầy đủ tất cả các khách hàng của doanh nghiệp mà chỉ gồm những khách hàng có phát sinh hợp đồng trong năm 2022 mà thôi. Điều này là do sau khi LEFT JOIN thì kết quả trả ra bao gồm tất cả các khách hàng, và với những khách hàng không phát sinh hợp đồng nào trong 2022 thì giá trị con.ContractDate sẽ là NULL, nên khi áp dụng mệnh đề WHERE vào thì các hợp đồng có con.ContractDate với giá trị NULL sẽ bị loại bỏ. Tóm lại thì query này trả ra kết quả giống như khi ta sử dụng INNER JOIN.

Để đáp ứng được yêu cầu của đề bài, ta cần phải áp dụng điều kiện lọc lên vế bên phải trước, sau đó mới thực hiện LEFT JOIN:


SELECT 
	cust.CustomerID, 
	cust.CustomerName,
	CFil.ContractNumber, 
	CFil.ContractDate, 
	CFil.ContractAmount
FROM Customers AS cust
LEFT JOIN
	(SELECT 
		CustomerID
		ContractNumber, 
		ContractDate,
		ContractAmount
	FROM Contracts
	WHERE ContractDate BETWEEN CAST('2022-01-01' AS DATE)
	AND CAST('2022-12-31' AS DATE)) AS CFil
ON cust.CustomerID = CFil.CustomerID;

Nếu ta muốn lấy ra chỉ những khách hàng mà không có phát sinh hợp đồng nào trong năm 2022 thì ta bổ sung thêm mệnh đề WHERE Cfil.CustomerID IS NULL vào cuối query trên (sau phần ON cust.CustomerID = Cfil.CustomerID)

Tổng kết lại, các bạn cần lưu ý:

  • Tùy vào yêu cầu của đề bài mà các bạn phải áp dụng điều kiện lọc (filter condition) trước hay sau khi join.
  • Nguyên tắc cơ bản là nếu muốn tìm các giá trị ở tập A mà không có ở tập B thì ta nên:
    • dùng LEFT OUTER JOIN (để join A với B, lấy tất cả giá trị ở A)
    • sau đó dùng mệnh đề WHERE để test giá trị NULL ở tập B (để lọc ra những giá trị ở A mà join với B không ra kết quả)
    • lưu ý là nếu có điều kiện lọc nào của B thì cần áp dụng lên B trước rồi mới join với A

Add a Comment

Your email address will not be published.