Antijunções e semijunções (NOT EXISTS)
Encontre “linhas em A sem correspondência em B” (antijunção) e “linhas em A com pelo menos uma correspondência em B” (semijunção) usando EXISTS/NOT EXISTS.
Antijunções e semijunções (NOT EXISTS) é uma aula grátis de SQL Academy no CoddyKit. Esta é a aula 3 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 Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Academy inclui 4 aulas no total.
Semi-join: "tem pelo menos uma correspondência"
Retorne as linhas de A que tenham pelo menos uma linha correspondente em B — mas somente as colunas de A. O SQL implementa semi-joins por meio de EXISTS ou IN.
Semi-join com EXISTS
Usuários que fizeram pelo menos um pedido:
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);Semi-join com IN
O mesmo resultado, com um estilo diferente:
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);Por que EXISTS geralmente vence
EXISTS interrompe a busca assim que encontra a primeira correspondência para cada linha externa. IN pode materializar todo o conjunto interno. Os planejadores modernos frequentemente otimizam ambos para o mesmo plano, mas EXISTS é a opção mais segura para conjuntos internos enormes.
Anti-join: "não tem correspondência"
Usuários que NEVER fizeram um pedido — três formas idiomáticas:
-- NOT EXISTS (preferred):
SELECT u.* FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
-- LEFT JOIN ... IS NULL:
SELECT u.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;
-- NOT IN (risky with NULLs):
SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM orders);Por que NOT IN é arriscado
Se a subconsulta interna contiver NULL, NOT IN retornará NULL — e WHERE descartará as linhas cujo predicado seja NULL. Resultado: zero linhas. NOT EXISTS não tem esse problema.
Otimização pelo planejador
O PostgreSQL moderno reconhece EXISTS e NOT EXISTS como padrões de semi-join/anti-join e pode executá-los com hash joins:
EXPLAIN ANALYZE
SELECT u.* FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-- → Hash Anti JoinAnti-joins com várias colunas
Use chaves compostas:
SELECT * FROM order_items oi
WHERE NOT EXISTS (
SELECT 1 FROM shipments s
WHERE s.order_id = oi.order_id
AND s.line_no = oi.line_no
);Semi-join com EXISTS + predicado adicional
Adicione filtros à subconsulta interna:
SELECT u.* FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
AND o.created_at >= NOW() - INTERVAL '30 days'
);Crie um índice na coluna de correlação
Tanto em EXISTS quanto em NOT EXISTS, a subconsulta interna filtra pela chave da linha externa. Sem um índice nessa chave, você terá uma varredura para cada linha externa:
CREATE INDEX orders_user_id_idx ON orders(user_id);Quando usar LEFT JOIN ... IS NULL
Para painéis que também precisam das colunas do lado sem correspondência, o estilo LEFT JOIN se encaixa naturalmente. Para a semântica pura de anti-join, NOT EXISTS é mais claro.
Além do SQL: filtros de Bloom
Para anti-joins enormes, um pré-filtro de Bloom pode ajudar. O PostgreSQL oferece índices bloom por meio da extensão bloom.
Recapitulação
Semi-join = "tem correspondência"; anti-join = "não tem correspondência".
- EXISTS para semi-join
- NOT EXISTS para anti-join (seguro para NULL)
- Crie um índice na coluna de correlação
- Evite NOT IN, a menos que a consulta interna não possa conter NULL
Verificação rápida
Você quer usuários que NEVER fizeram um pedido. Qual é o SQL mais seguro e idiomático?
Perguntas Frequentes
A aula “Antijunções e semijunções (NOT EXISTS)” é grátis?
Sim — o texto completo de “Antijunções e semijunções (NOT EXISTS)” é 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 Academy, atualize para CoddyKit PRO. O curso de SQL Academy inclui 4 aulas no total.
O que vou aprender em “Antijunções e semijunções (NOT EXISTS)”?
Encontre “linhas em A sem correspondência em B” (antijunção) e “linhas em A com pelo menos uma correspondência em B” (semijunção) usando EXISTS/NOT EXISTS. Você pratica SQL Academy 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 Academy?
Nenhuma experiência prévia é necessária. SQL Academy 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 3 de 4.
Quanto tempo leva a aula “Antijunções e semijunções (NOT EXISTS)”?
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 Academy?
Sim. Cada aula de SQL Academy 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
- Junções cruzadas e produtos cartesianos
- Junções laterais (LATERAL JOIN)
- Antijunções e semijunções (NOT EXISTS)
- Ajuste de desempenho de junções entre várias tabelas