Faites juste attention à la différence avec les jointures externes. Une requête où un filtre b.IsApproved
(sur le tableau de droite, Bar) est ajouté au ON
condition du JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
N'est PAS revient à placer le filtre dans WHERE
clause :
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Puisque pour les jointures externes 'échouées' à Bar
(c'est-à-dire lorsqu'il n'y a pas de b.BarId
pour un f.BarId
), cela laissera b.IsApproved
comme NULL
pour toutes ces lignes de jointure ayant échoué, et ces lignes seront alors filtrées.
Une autre façon de voir cela est que pour la première requête, LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
renverra toujours les lignes de la table LEFT, puisque LEFT OUTER JOIN
garantit que les lignes de la table LEFT seront renvoyées même si la jointure échoue. Cependant, l'effet de l'ajout de (b.IsApproved = 1)
à la LEFT OUTER JOIN
la condition est de NULL sur toutes les colonnes de table de droite lorsque (b.IsApproved = 1)
est faux, c'est-à-dire selon les mêmes règles normalement appliquées à un LEFT JOIN
condition sur (b.BarId = f.BarId)
.
Mettre à jour :Pour compléter la question posée par Conrad, la LOJ équivalente pour un filtre OPTIONAL serait :
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
c'est-à-dire le WHERE
la clause doit considérer à la fois la condition d'échec de la jointure (NULL)
et le filtre doit être ignoré, et où la jointure réussit et le filtre doit être appliqué. (b.IsApproved
ou b.BarId
pourrait être testé pour NULL
)
J'ai rassemblé ici un SqlFiddle qui montre les différences entre les différents emplacements du b.IsApproved
filtre relatif au JOIN
.