Subqueries & EXISTS
EXISTS verifica a presença sem retornar linhas duplicadas de um filho um-para-muitos. IN funciona para pequenos conjuntos estáticos; EXISTS escala melhor para semi-joins correlacionados.
Receita
SELECT c.id, c.email
FROM app.customers c
WHERE EXISTS (
SELECT 1 FROM app.orders o
WHERE o.customer_id = c.id AND o.total > 1000
);
SELECT id FROM app.customers
WHERE id IN (SELECT customer_id FROM app.orders WHERE total > 1000);Quando usar isso: Este padrão aparece em SQL de aplicação ou relatórios que você mantém.
Exemplo de Trabalho
SELECT c.email
FROM app.customers c
WHERE NOT EXISTS (
SELECT 1 FROM app.orders o WHERE o.customer_id = c.id
);O que isso demonstra:
- EXISTS para a execução na primeira correspondência
- NOT EXISTS encontra clientes sem pedidos
- Equivalente a IN quando a chave filha é única por filtro pai
Análise Detalhada
Como Funciona
- O PostgreSQL analisa o SQL em uma árvore de consulta.
- O planejador estima os custos usando estatísticas.
- O executor retorna linhas para o protocolo do cliente.
Notas
- Prefira SQL legível; otimizadores reescrevem internamente.
- Teste com contagens de linhas semelhantes à produção.
Armadilhas
- IN com NULL na subquery - Desconhecido envenena o resultado para desconhecido. Correção: Use NOT EXISTS ou force chaves NOT NULL.
- Grandes listas IN - Milhares de literais analisam lentamente. Correção: Use join de tabela temporária ou = ANY(array).
- Custo de loop aninhado correlacionado - EXISTS por linha externa sem índice. Correção: Indexe colunas de join filho.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Construtor de consulta ORM | Equipe padroniza em uma única stack | SQL complexo se torna opaco |
| View Materializada | Agregados caros repetidos | Necessita de estratégia de atualização |
| Réplica de Data Warehouse | Varreduras pesadas de BI | Não para latência OLTP |
FAQs
Devo formatar SQL em strings de aplicação?
Use strings de template multilinhas ou arquivos SQL; faça lint no CI.
Quando DISTINCT é suficiente?
Quando você precisa de linhas únicas sem agregações.
ORDER BY prejudica índices?
A ordenação pode usar a ordem do índice se a consulta corresponder às colunas do índice.
Relacionado
- Tipos de JOIN - quando join substitui exists
- Joins LATERAL - subqueries por linha
Versões da Stack: Esta página foi escrita para PostgreSQL 18.4 (estável 18, manutenção 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, e PostGIS 3.5+.