Solo tenga cuidado con la diferencia con las uniones externas. Una consulta donde un filtro de b.IsApproved
(en la tabla de la derecha, Bar) se agrega a ON
condición de JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
NO lo mismo que colocar el filtro en el WHERE
cláusula:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Dado que para uniones externas 'fallidas' a Bar
(es decir, donde no hay b.BarId
para un f.BarId
), esto dejará b.IsApproved
como NULL
para todas esas filas de combinación fallidas, y estas filas luego se filtrarán.
Otra forma de ver esto es que para la primera consulta, LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
siempre devolverá las filas de la tabla IZQUIERDA, ya que LEFT OUTER JOIN
garantiza que se devolverán las filas de la tabla IZQUIERDA incluso si falla la combinación. Sin embargo, el efecto de agregar (b.IsApproved = 1)
a la LEFT OUTER JOIN
con la condición de anular cualquier columna de la tabla derecha cuando (b.IsApproved = 1)
es falso, es decir, según las mismas reglas que normalmente se aplican a un LEFT JOIN
condición en (b.BarId = f.BarId)
.
Actualizar :Para completar la pregunta de Conrad, el LOJ equivalente para un filtro OPCIONAL sería:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
es decir, el WHERE
la cláusula debe considerar tanto la condición de si la unión falla (NULL)
y el filtro debe ignorarse, y donde la combinación tiene éxito y debe aplicarse el filtro. (b.IsApproved
o b.BarId
podría probarse para NULL
)
He reunido un SqlFiddle aquí que demuestra las diferencias entre las distintas ubicaciones de b.IsApproved
filtro relativo a JOIN
.