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?

Foi útil?

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 [um id] é não nulo )

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:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top