Achten Sie nur auf den Unterschied zu äußeren Verknüpfungen. Eine Abfrage, bei der ein Filter von b.IsApproved
verwendet wird (auf dem rechten Tisch, Bar) wird zum ON
hinzugefügt Bedingung des JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
Ist NICHT dasselbe wie das Platzieren des Filters im WHERE
Klausel:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Da für 'fehlgeschlagene' Outer Joins zu Bar
(d.h. wo es kein b.BarId
gibt für eine f.BarId
), bleibt b.IsApproved
übrig als NULL
für alle solchen fehlgeschlagenen Join-Zeilen, und diese Zeilen werden dann herausgefiltert.
Eine andere Sichtweise ist, dass für die erste Abfrage LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
gibt immer die LEFT-Tabellenzeilen zurück, da LEFT OUTER JOIN
garantiert, dass die LEFT-Tabellenzeilen zurückgegeben werden, selbst wenn der Join fehlschlägt. Allerdings wirkt sich das Hinzufügen von (b.IsApproved = 1)
aus zum LEFT OUTER JOIN
Eine Bedingung ist, alle rechten Tabellenspalten auf NULL zu setzen, wenn (b.IsApproved = 1)
falsch ist, d. h. nach denselben Regeln, die normalerweise auf einen LEFT JOIN
angewendet werden Bedingung für (b.BarId = f.BarId)
.
Aktualisieren :Um die von Conrad gestellte Frage zu vervollständigen, wäre der entsprechende LOJ für einen OPTIONALEN Filter:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
d.h. das WHERE
-Klausel muss sowohl die Bedingung berücksichtigen, ob der Join (NULL)
fehlschlägt und der Filter ignoriert werden soll, und wo die Verknüpfung erfolgreich ist und der Filter angewendet werden muss. (b.IsApproved
oder b.BarId
könnte auf NULL
getestet werden )
Ich habe hier ein SqlFiddle zusammengestellt, das die Unterschiede zwischen den verschiedenen Platzierungen des b.IsApproved
demonstriert Filter relativ zum JOIN
.