Chỉ cần cẩn thận về sự khác biệt với các mối nối bên ngoài. Một truy vấn trong đó bộ lọc b.IsApproved
(trên bảng bên phải, Thanh) được thêm vào ON
điều kiện của JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
KHÔNG giống như đặt bộ lọc trong WHERE
mệnh đề:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Vì cho các phép nối bên ngoài 'không thành công' vào Bar
(tức là không có b.BarId
cho một f.BarId
), điều này sẽ để lại b.IsApproved
dưới dạng NULL
cho tất cả các hàng nối không thành công như vậy, và các hàng này sau đó sẽ được lọc ra.
Một cách khác để xem xét vấn đề này là đối với truy vấn đầu tiên, LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
sẽ luôn trả về các hàng của bảng TRÁI, vì LEFT OUTER JOIN
đảm bảo các hàng của bảng TRÁI sẽ được trả về ngay cả khi phép nối không thành công. Tuy nhiên, ảnh hưởng của việc thêm (b.IsApproved = 1)
vào LEFT OUTER JOIN
với điều kiện là NULL bất kỳ cột bên phải nào trong bảng khi (b.IsApproved = 1)
là sai, tức là theo các quy tắc tương tự thường được áp dụng cho LEFT JOIN
điều kiện trên (b.BarId = f.BarId)
.
Cập nhật :Để hoàn thành câu hỏi do Conrad hỏi, LOJ tương đương cho bộ lọc TÙY CHỌN sẽ là:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
tức là WHERE
mệnh đề cần phải xem xét cả điều kiện cho dù kết nối không thành công (NULL)
và bộ lọc sẽ bị bỏ qua và nơi nối thành công và bộ lọc phải được áp dụng. (b.IsApproved
hoặc b.BarId
có thể được kiểm tra cho NULL
)
Tôi đã đặt một SqlFiddle lại với nhau ở đây để thể hiện sự khác biệt giữa các vị trí khác nhau của b.IsApproved
bộ lọc liên quan đến JOIN
.