Apenas tome cuidado com a diferença com junções externas. Uma consulta em que um filtro de
b.IsApproved
(na tabela à direita, Bar) é adicionado ao ON
condição do JOIN
:SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
É NÃO o mesmo que colocar o filtro em
WHERE
cláusula:SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Como para junções externas 'falhadas' para
Bar
(ou seja, onde não há b.BarId
para um f.BarId
), isso deixará b.IsApproved
como NULL
para todas essas linhas de junção com falha, e essas linhas serão filtradas. Outra maneira de ver isso é que, para a primeira consulta,
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
sempre retornará as linhas da tabela LEFT, pois LEFT OUTER JOIN
garante que as linhas da tabela LEFT serão retornadas mesmo se a junção falhar. No entanto, o efeito de adicionar (b.IsApproved = 1)
para o LEFT OUTER JOIN
na condição é NULL qualquer coluna da tabela à direita quando (b.IsApproved = 1)
é falso, ou seja, de acordo com as mesmas regras normalmente aplicadas a um LEFT JOIN
condição em (b.BarId = f.BarId)
. Atualizar :Para completar a pergunta feita por Conrad, o LOJ equivalente para um filtro OPCIONAL seria:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
ou seja, o
WHERE
A cláusula precisa considerar tanto a condição se a junção falha (NULL)
e o filtro deve ser ignorado e onde a junção for bem-sucedida e o filtro deve ser aplicado. (b.IsApproved
ou b.BarId
pode ser testado para NULL
) Eu coloquei um SqlFiddle aqui que demonstra as diferenças entre os vários posicionamentos do
b.IsApproved
filtro relativo ao JOIN
.