Berhati-hatilah dengan perbedaan dengan gabungan luar. Kueri di mana filter b.IsApproved
(di tabel kanan, Bar) ditambahkan ke ON
kondisi JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
Apakah TIDAK sama dengan menempatkan filter di WHERE
klausa:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Karena untuk 'gagal' luar bergabung ke Bar
(yaitu di mana tidak ada b.BarId
untuk f.BarId
), ini akan meninggalkan b.IsApproved
sebagai NULL
untuk semua baris gabungan yang gagal tersebut, dan baris ini kemudian akan disaring.
Cara lain untuk melihat ini adalah bahwa untuk kueri pertama, LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
akan selalu mengembalikan baris tabel KIRI, karena LEFT OUTER JOIN
menjamin baris tabel KIRI akan dikembalikan bahkan jika gabungan gagal. Namun, efek penambahan (b.IsApproved = 1)
ke LEFT OUTER JOIN
dengan syarat adalah NULL kolom tabel kanan saat (b.IsApproved = 1)
salah, yaitu sesuai dengan aturan yang sama yang biasanya diterapkan pada LEFT JOIN
kondisi pada (b.BarId = f.BarId)
.
Perbarui :Untuk menyelesaikan pertanyaan yang diajukan oleh Conrad, LOJ yang setara untuk filter OPSIONAL adalah:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
yaitu WHERE
klausa perlu mempertimbangkan kedua kondisi apakah penggabungan gagal (NULL)
dan filter harus diabaikan, dan di mana gabungan berhasil dan filter harus diterapkan. (b.IsApproved
atau b.BarId
dapat diuji untuk NULL
)
Saya telah menggabungkan SqlFiddle di sini yang menunjukkan perbedaan antara berbagai penempatan b.IsApproved
filter relatif terhadap JOIN
.