Emulando operações de conjuntos com junções
Reescreva EXCEPT e INTERSECT em dialetos que não os oferecem.
Emulando operações de conjuntos com junções é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.
Por que reproduzir operações de conjuntos
Nem todo banco de dados oferece INTERSECT e EXCEPT. Versões antigas do MySQL, por exemplo, não os ofereciam de forma alguma. Os entrevistadores verificam se você consegue reproduzir a lógica de conjuntos com operações JOIN e subconsultas quando o operador não está disponível.
Conhecer tanto o operador de conjuntos quanto seu equivalente com JOIN demonstra que você entende o que o operador realmente calcula.
INTERSECT como um INNER JOIN
INTERSECT encontra as linhas comuns aos dois conjuntos. O equivalente com JOIN é um INNER JOIN sobre todas as colunas comparadas, além de DISTINCT para reproduzir o comportamento de deduplicação.
Cada coluna da comparação se torna parte do predicado da operação JOIN.
-- A INTERSECT B emulated:
SELECT DISTINCT a.customer_id
FROM orders_2023 a
JOIN orders_2024 b
ON a.customer_id = b.customer_id;Por que DISTINCT é necessário para INTERSECT
Um INNER JOIN simples pode expandir os resultados: se um valor aparecer várias vezes em qualquer um dos lados, a operação JOIN multiplicará as linhas. O INTERSECT padrão retorna cada linha comum uma única vez, portanto você adiciona DISTINCT para eliminar as duplicatas introduzidas pela operação JOIN.
Esquecer DISTINCT aqui é um erro comum em entrevistas.
-- without DISTINCT, a customer with 3 orders in each year
-- would appear 9 times from the joinEXCEPT como LEFT JOIN / IS NULL
EXCEPT (A, mas não B) é a antijunção. A forma portável é um LEFT JOIN de A para B com base em todas as colunas, mantendo apenas as linhas em que o lado B é NULL (sem correspondência) e, em seguida, aplicando DISTINCT.
Esse padrão LEFT JOIN / IS NULL é um dos truques mais reutilizados em entrevistas de SQL.
SELECT DISTINCT a.customer_id
FROM orders_2023 a
LEFT JOIN orders_2024 b
ON a.customer_id = b.customer_id
WHERE b.customer_id IS NULL;EXCEPT com NOT EXISTS
Uma forma igualmente portável de usar EXCEPT emprega NOT EXISTS. Ela pode ser lida como "mantenha cada linha de A para a qual não exista nenhuma linha correspondente de B" e lida robustamente com valores NULL.
Muitos engenheiros preferem NOT EXISTS porque sua intenção é explícita e ele evita a armadilha de NOT IN + NULL.
SELECT DISTINCT a.customer_id
FROM orders_2023 a
WHERE NOT EXISTS (
SELECT 1 FROM orders_2024 b
WHERE b.customer_id = a.customer_id
);INTERSECT com EXISTS
De forma simétrica, INTERSECT pode ser escrito com EXISTS: mantenha cada linha distinta de A para a qual exista uma linha correspondente de B.
EXISTS interrompe a busca ao encontrar a primeira correspondência, portanto pode ser eficiente e evita a multiplicação de linhas da junção, às vezes eliminando a necessidade de DISTINCT no lado da junção.
SELECT DISTINCT a.customer_id
FROM orders_2023 a
WHERE EXISTS (
SELECT 1 FROM orders_2024 b
WHERE b.customer_id = a.customer_id
);A armadilha de NOT IN com NULL
Uma emulação tentadora de EXCEPT é NOT IN, mas ela é perigosa: se a subconsulta retornar qualquer valor NULL, NOT IN não retornará linha alguma, porque a comparação se torna UNKNOWN.
Essa é uma armadilha muito cobrada em testes. Prefira NOT EXISTS ou LEFT JOIN / IS NULL, que lidam com NULL com segurança.
-- RISKY if orders_2024.customer_id can be NULL:
SELECT DISTINCT customer_id FROM orders_2023
WHERE customer_id NOT IN (
SELECT customer_id FROM orders_2024
);Correspondência em várias colunas
Quando a comparação de conjuntos abrange várias colunas, todas elas entram no predicado da junção. Em uma antijunção, também é necessário lidar com a possibilidade de haver valores NULL nessas colunas; é nesse ponto que NOT EXISTS se destaca.
Especifique cada coluna na cláusula ON; deixar uma de fora altera silenciosamente o significado de "linha igual".
SELECT DISTINCT a.id, a.city
FROM a
LEFT JOIN b
ON a.id = b.id AND a.city = b.city
WHERE b.id IS NULL;Emulando UNION sem o operador
UNION ALL é apenas concatenação, algo que todo dialeto oferece diretamente. Para emular UNION distinto quando necessário, concatene com UNION ALL dentro de uma subconsulta e envolva o resultado com SELECT DISTINCT ou GROUP BY em todas as colunas.
Isso mostra que UNION é simplesmente UNION ALL mais uma etapa de remoção de duplicatas.
SELECT DISTINCT * FROM (
SELECT city FROM a
UNION ALL
SELECT city FROM b
) combined;Escolhendo a emulação adequada
Guia de decisão:
- INTERSECT →
EXISTSou INNER JOIN + DISTINCT. - EXCEPT →
NOT EXISTSou LEFT JOIN / IS NULL. - Evite
NOT INquando houver possibilidade de NULL. - UNION → UNION ALL envolvido em DISTINCT.
EXISTS / NOT EXISTS são as opções mais portáveis e seguras para NULL, o que as torna as respostas mais seguras em entrevistas.
Conectando tudo
Saber traduzir operadores de conjuntos em junções demonstra que você os entende como lógica de conjuntos, e não apenas como sintaxe. A antijunção (LEFT JOIN / IS NULL ou NOT EXISTS) é o padrão de maior valor: ela aparece na emulação de EXCEPT, na localização de registros órfãos e em questões sobre registros ausentes.
Comece por NOT EXISTS para garantir a correção e, depois, mencione a forma com junção ao discutir desempenho.
Verificação rápida
Seu banco de dados não oferece suporte a EXCEPT. Você precisa dos customer_ids presentes em orders_2023 que não estejam em orders_2024, e a coluna pode conter valores NULL.
Recapitulação
Principais conclusões:
INTERSECT→ INNER JOIN + DISTINCT ouEXISTS.EXCEPT→ LEFT JOIN / IS NULL ouNOT EXISTS(antijunção).- Adicione
DISTINCTpara reproduzir o comportamento de remoção de duplicatas dos operadores de conjuntos e controlar a multiplicação de linhas da junção. - Evite
NOT INquando houver possibilidade de NULL; prefira NOT EXISTS. UNION= UNION ALL envolvido em DISTINCT.
Perguntas Frequentes
A aula “Emulando operações de conjuntos com junções” é grátis?
Sim — o texto completo de “Emulando operações de conjuntos com junções” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.
O que vou aprender em “Emulando operações de conjuntos com junções”?
Reescreva EXCEPT e INTERSECT em dialetos que não os oferecem. Você pratica SQL Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Interview Prep?
Nenhuma experiência prévia é necessária. SQL Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Emulando operações de conjuntos com junções”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Interview Prep?
Sim. Cada aula de SQL Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- UNION versus UNION ALL
- Compatibilidade de quantidade e tipos de colunas
- INTERSECT e EXCEPT para comparação
- Emulando operações de conjuntos com junções