Voltar para a lista de artigos Artigos
7 minutos de leitura

Qual é a diferença entre ON e WHERE em SQL JOINs?

Quando você une tabelas em SQL, você pode ter condições em uma cláusula ON e em uma cláusula WHERE. Muitos ficam confusos com a diferença entre elas. Neste artigo, discutiremos este tópico primeiro lembrando-lhe o propósito das cláusulas ON e WHERE e depois demonstrando com exemplos que tipos de condições devem estar em cada uma dessas cláusulas.

Tanto a cláusula ON quanto a cláusula WHERE podem especificar as condições. Mas há alguma diferença entre elas? Em caso positivo, onde você deve especificar quais condições em sua consulta SQL? Vamos descobrir juntos!

ON vs. WHERE Condições

O objetivo da cláusula ON é especificar as condições de adesão, ou seja, definir como as tabelas devem ser unidas. Especificamente, você define como os registros devem ser emparelhados.

Em contraste, a finalidade da cláusulaWHERE é especificar as condições de filtragem, ou seja, definir quais linhas devem ser mantidas no conjunto de resultados.

Vejamos um exemplo para entender a diferença. Temos as seguintes duas tabelas que (1) listam os usuários (a tabela users) de nosso site de aluguel e (2) listar as casas (a tabela houses) disponível para aluguel.

users
idnameregistration_date
11Jane Stewart2020-11-30
12Mary Cooper2015-06-12
13John Watson2015-01-31
14Christian Wood2018-03-03
15William Grey2021-05-12
16Brandon Evans2018-05-08
17Isabella Gonsalez2020-12-12
18Diana Taylor2020-06-30
19Luke Wilson2019-11-17
20Michael Lee2020-02-15

houses
idaddresscityowner_idbedrooms
101Brook Street, 5Cardiff124
102Richmond Street, 1Cardiff121
103Cromwell Road, 23Liverpool132
104Hastings Road, 109York152
105Bedford Road, 2Bristol161
106Queen Street, 45Bristol163
107Mayfield Road, 34Cardiff123
SELECT u.id, u.name, u.registration_date, h.address, h.city
FROM users u
JOIN houses h
ON u.id = h.owner_id
WHERE u.registration_date < '2020-01-01';

Observe que temos condições tanto na cláusula ON quanto na cláusula WHERE:

  • Com a condição ON, especificamos que as tabelas devem ser unidas pela correspondência entre a coluna id na tabela de usuários e a coluna owner_id nas casas.
  • Com a condição WHERE, filtramos o resultado definido, mantendo apenas os usuários que se registraram antes de 1 de janeiro de 2020.

Assim, utilizamos as condições ON e WHERE de acordo com sua finalidade, resultando em uma consulta SQL clara e legível.

Aqui está o resultado definido:

idnameregistration_dateaddresscity
12Mary Cooper2015-06-12Brook Street, 5Cardiff
12Mary Cooper2015-06-12Richmond Street, 1Cardiff
13John Watson2015-01-31Cromwell Road, 23Liverpool
16Brandon Evans2018-05-08Bedford Road, 2Bristol
16Brandon Evans2018-05-08Queen Street, 45Bristol
12Mary Cooper2015-06-12Mayfield Road, 34Cardiff

Não tem certeza de como o JOIN funciona em nossa consulta SQL? Pratique unindo tabelas com este curso interativo de SQL JOINs.

ON e WHERE Condições em INNER JOINs

No exemplo acima, podemos ver como as condições ON e WHERE são utilizadas de acordo com sua respectiva finalidade e prática comum.

Entretanto, é útil saber que, para (INNER) JOINs, pode-se especificar tanto a condição JOIN quanto a condição de filtragem com uma cláusula ON. Por exemplo, podemos obter o mesmo resultado que o acima com a seguinte consulta SQL:

SELECT u.id, u.name, u.registration_date, h.address, h.city
FROM users u
JOIN houses h
ON u.id = h.owner_id AND u.registration_date < '2020-01-01';

Esta consulta é executada da mesma forma. Dito isto, não recomendo misturar a condição de join e a condição de filtragem na mesma cláusula. Se você comparar as duas consultas, você verá que a primeira é mais legível:

  • É mais fácil seguir a primeira consulta: primeiro, você une as tabelas por uma determinada condição, depois filtra o resultado por uma condição diferente.
  • A intenção de toda a consulta é mais clara para o leitor externo quando as condições são separadas, seguindo as regras.

ON e ON ON ON ON e WHERE Condições em OUTER JOINs

Quando se trata de OUTER JOINs (ou seja, LEFT JOIN, RIGHT JOIN, e FULL JOIN), é crucial utilizar as condições de ON e WHERE da maneira como elas são destinadas. Caso contrário, você obterá resultados errados. Vamos ver com um exemplo.

Mais uma vez, queremos obter a lista de usuários que se registraram antes de 1º de janeiro de 2020, juntamente com suas respectivas casas. Desta vez, porém, queremos manter todos os usuários, inclusive aqueles que não têm casas registradas em nosso site de locação. Assim, vamos fazer um LEFT JOIN ao invés de um JOIN (ou seja, um INNER JOIN).

Veremos se existem diferenças entre especificar a condição de filtragem na cláusula ON e especificá-la na cláusula WHERE. Se seguirmos as regras e usarmos as condições como pretendido, teremos a seguinte consulta:

SELECT u.id, u.name, u.registration_date, h.address, h.city
FROM users u
LEFT JOIN houses h
ON u.id = h.owner_id
WHERE u.registration_date < '2020-01-01';
idnameregistration_dateaddresscity
12Mary Cooper2015-06-12Brook Street, 5Cardiff
12Mary Cooper2015-06-12Richmond Street, 1Cardiff
13John Watson2015-01-31Cromwell Road, 23Liverpool
16Brandon Evans2018-05-08Bedford Road, 2Bristol
16Brandon Evans2018-05-08Queen Street, 45Bristol
12Mary Cooper2015-06-12Mayfield Road, 34Cardiff
19Luke Wilson2019-11-17NULLNULL
14Christian Wood2018-03-03NULLNULL

O resultado parece bom. Temos todos os usuários que temos em nosso exemplo inicial. Além disso, temos mais dois usuários que não têm casas correspondentes em nosso site, mas foram incluídos no conjunto de resultados devido ao LEFT JOIN. Note que ambos se registraram antes de 1º de janeiro de 2020, conforme especificado em nossa condição de filtragem.

Obteremos o mesmo resultado se misturarmos a condição de junção e a condição de filtragem na cláusula ON? Vamos descobrir:

SELECT u.id, u.name, u.registration_date, h.address, h.city
FROM users u
LEFT JOIN houses h
ON u.id = h.owner_id AND u.registration_date < '2020-01-01';
idnameregistration_dateaddresscity
11Jane Stewart2020-11-30NULLNULL
12Mary Cooper2015-06-12Mayfield Road, 34Cardiff
12Mary Cooper2015-06-12Richmond Street, 1Cardiff
12Mary Cooper2015-06-12Brook Street, 5Cardiff
13John Watson2015-01-31Cromwell Road, 23Liverpool
14Christian Wood2018-03-03NULLNULL
15William Grey2021-05-12NULLNULL
16Brandon Evans2018-05-08Queen Street, 45Bristol
16Brandon Evans2018-05-08Bedford Road, 2Bristol
17Isabella Gonsalez2020-12-12NULLNULL
18Diana Taylor2020-06-30NULLNULL
19Luke Wilson2019-11-17NULLNULL
20Michael Lee2020-02-15NULLNULL

Como você pode ver, os resultados são diferentes. Temos todos os usuários incluídos, mesmo aqueles que se registraram em 2020 ou 2021. Isto porque o LEFT JOIN mantém todos os registros da tabela da esquerda mesmo quando a lógica do ON falha. Portanto, neste exemplo, especificar a condição de filtragem na cláusula ON não funciona para nós. Para obter o resultado correto, precisamos especificar as condições conforme pretendido.

Curiosamente, há situações em que a condição WHERE pode "cancelar" a intenção de um OUTER JOIN. Como exemplo, digamos que queremos listar todos os usuários com suas casas correspondentes, mas somente se as casas tiverem 3 ou mais quartos.

Como queremos manter todos os usuários, usaremos um OUTER JOIN, especificamente um LEFT JOIN. Nossa exigência quanto ao número de quartos é claramente uma condição de filtragem. Portanto, vamos incluí-la na cláusula WHERE. Aqui está nossa consulta SQL com as condições especificadas como pretendido:

SELECT u.id, u.name, h.address, h.city, h.bedrooms
FROM users u
LEFT JOIN houses h
ON u.id = h.owner_id
WHERE h.bedrooms > 2;

Não parece correto, não é mesmo? O resultado parece que usamos um INNER JOIN em vez de um LEFT JOIN. Os usuários sem casas não são incluídos na tabela resultante, pois eles têm NULL na coluna de quartos quando as mesas são unidas. Como os valores de NULL são considerados inferiores a 0, as linhas correspondentes são removidas quando aplicamos a condição de filtragem - o número de dormitórios superior a 2.

Há duas soluções possíveis para este problema:

  • Adicionar outra condição de filtragem à cláusula WHERE, como os dormitórios é NULL:
    SELECT u.id, u.name, h.address, h.city, h.bedrooms
    FROM users u
    LEFT JOIN houses h
    ON u.id = h.owner_id
    WHERE h.bedrooms > 2 OR h.bedrooms is NULL;
    
  • Movendo a condição de filtragem para a cláusula ON:
    SELECT u.id, u.name, h.address, h.city, h.bedrooms
    FROM users u
    LEFT JOIN houses h
    ON u.id = h.owner_id AND h.bedrooms > 2;
    

Qualquer uma destas consultas nos dá o seguinte resultado:



idnameaddresscitybedrooms
11Jane StewartNULLNULLNULL
12Mary CooperMayfield Road, 34Cardiff3
12Mary CooperBrook Street, 5Cardiff4
13John WatsonCromwell Road, 23LiverpoolNULL
14Christian WoodNULLNULLNULL
15William GreyNULLNULLNULL
16Brandon EvansQueen Street, 45Bristol3
17Isabella GonsalezNULLNULLNULL
18Diana TaylorNULLNULLNULL
19Luke WilsonNULLNULLNULL
20Michael LeeNULLNULLNULL

Agora você já sabe! Em OUTER JOINs, faz uma diferença como especificamos as condições.

Vamos praticar o JOINs em SQL!

SQL JOINs não são muito difíceis de entender. Entretanto, como você pode ver nos exemplos deste artigo, há nuances que devem ser consideradas ao unir tabelas e escrever condições de união em SQL.

Se você realmente quer dominar Cláusulas JOIN em SQL, praticar com conjuntos de dados do mundo real é um fator chave de sucesso. Recomendo começar com o curso interativo SQL JOINs - ele inclui 93 desafios de codificação cobrindo os tipos mais comuns de junções como JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN, e até mesmo auto junções e junções não-equi. Após este curso, você saberá como unir várias tabelas, como unir tabelas sem uma coluna comum, e como filtrar corretamente os dados com diferentes tipos de JOINs.

Para aqueles que querem experiência com ainda mais casos de uso SQL JOIN, recomendo levar o Trilha de Práticas em SQL pista. Inclui cinco cursos interativos com mais de 600 desafios de codificação, cobrindo não apenas o básico de Cláusulas JOIN em SQL mas também como filtrar o conjunto de resultados com uma cláusula WHERE, como agregar dados com GROUP BY e HAVING, e como utilizar subconsultas incluindo subconsultas correlatas. Você vai se divertir muito!

BÔNUS. Aqui estão as 10 principais perguntas da entrevista SQL JOIN com respostas.