Domanda

Ho due tabelle che sono unite insieme.

A ha molti B

Normalmente faresti:

select * from a,b where b.a_id = a.id

Per ottenere tutti i record da un che ha un record in b.

Come posso ottenere solo i record in a che non hanno nulla in b?

È stato utile?

Soluzione

select * from a where id not in (select a_id from b)

O come altre persone su questo thread dicono:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null

Altri suggerimenti

select * from a
left outer join b on a.id = b.a_id
where b.a_id is null

Un altro approccio:

select * from a where not exists (select * from b where b.a_id = a.id)

Il " esiste " l'approccio è utile se esiste qualche altro "dove" clausola che devi allegare alla query interna.

SELECT id FROM a
EXCEPT
SELECT a_id FROM b;

seleziona * da un ID in cui non si trova (seleziona a_id da b)

Probabilmente otterrai prestazioni molto migliori (rispetto all'uso di 'non in') se usi un join esterno:

select * from a left outer join b on a.id = b.a_id where b.a_id is null;

Questo ti proteggerà da null nella clausola IN, che può causare comportamenti imprevisti.

seleziona * da un ID dove non è presente (seleziona [un ID] da b dove [un ID] non è nullo )

Nel caso di un join è piuttosto veloce, ma quando stiamo rimuovendo i record dal database che ha circa 50 milioni di record e 4 e più join a causa di chiavi esterne, ci vogliono alcuni minuti per farlo. Molto più veloce da usare in condizioni WHERE NOT IN come questa:

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)

Posso anche raccomandare questo approccio per l'eliminazione nel caso in cui non abbiamo configurato l'eliminazione in cascata. Questa query richiede solo pochi secondi.

Il primo approccio è

select a.* from a where a.id  not in (select b.ida from b)

il secondo approccio è

select a.*
  from a left outer join b on a.id = b.ida
  where b.ida is null

Il primo approccio è molto costoso. Il secondo approccio è migliore.

Con PostgreSql 9.4 ho fatto la "spiegazione della query" funzione e la prima query come costo di costo = 0,00..1982043603.32 . Invece la query di join ha un costo di cost=45946.77..45946.78

Ad esempio, cerco tutti i prodotti che non sono compatibili senza veicoli. Ho 100.000 prodotti e oltre 1 milione di compatibilità.

select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null

La query di join ha impiegato circa 5 secondi, invece la versione della sottoquery non è mai terminata dopo 3 minuti.

Un altro modo di scriverlo

select a.*
from a 
left outer join b
on a.id = b.id
where b.id is null

Ouch, battuto da Nathan :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top