Como faço para encontrar registros que não são unidas?
Pergunta
Eu tenho duas tabelas que são unidas.
A tem muitos B
Normalmente, você faria:
select * from a,b where b.a_id = a.id
Para obter todos os registros de um que tem um histórico em b.
Como faço para obter apenas os registros em um que não tem nada em b?
Solução
select * from a where id not in (select a_id from b)
Ou como algumas outras pessoas sobre esta discussão diz:
select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null
Outras dicas
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
Outra abordagem:
select * from a where not exists (select * from b where b.a_id = a.id)
O "existe" abordagem é útil se houver alguma outra cláusula "where" que você precisa para anexar a consulta interna.
SELECT id FROM a
EXCEPT
SELECT a_id FROM b;
SELECT * FROM uma onde id não em (selecione A_ID de b)
Você provavelmente vai ficar muito melhor desempenho (do que usar 'não em') se você usar uma associação externa:
select * from a left outer join b on a.id = b.a_id where b.a_id is null;
Isso irá protegê-lo de nulos na cláusula IN, o que pode causar um comportamento inesperado.
* seleccione a partir de um ID, onde não em (seleccione [a id] a partir de b onde
Em caso de uma junção é bastante rápido, mas quando estamos removendo os registros do banco de dados que tem cerca de 50 milions registros e 4 e mais junta-se devido a chaves estrangeiras, que leva alguns minutos para fazê-lo. Muito mais rápido de usar WHERE NOT IN condição como esta:
select a.* from a
where a.id NOT IN(SELECT DISTINCT a_id FROM b where a_id IS NOT NULL)
//And for more joins
AND a.id NOT IN(SELECT DISTINCT a_id FROM c where a_id IS NOT NULL)
Eu também posso recomendou esta abordagem para apagar em caso nós não tiver configurado exclusão em cascata. Esta consulta leva apenas alguns segundos.
A primeira abordagem é
select a.* from a where a.id not in (select b.ida from b)
A segunda abordagem é
select a.*
from a left outer join b on a.id = b.ida
where b.ida is null
A primeira abordagem é muito caro. A segunda abordagem é melhor.
Com o PostgreSQL 9.4, eu fiz a "explicar consulta" função ea primeira consulta como um custo de custo = 0.00..1982043603.32 . Em vez disso a consulta juntar-se como um custo de custo = 45946.77..45946.78
Por exemplo, eu procurar todos os produtos que não são compatíveis com nenhum veículo. Eu tenho 100k produtos e mais de compatibilidades 1m.
select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null
A consulta de junção gastou cerca de 5 segundos, em vez da versão subconsulta nunca terminou após 3 minutos.
Outra forma de escrevê-lo
select a.*
from a
left outer join b
on a.id = b.id
where b.id is null
Ouch, batido por Nathan:)