web-dev-qa-db-fra.com

Comment trouver des enregistrements qui ne sont pas joints?

J'ai deux tables qui sont jointes. 

A a beaucoup de B

Normalement, vous feriez: 

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

Pour obtenir tous les enregistrements d'un a qui a un enregistrement dans b. 

Comment obtenir uniquement les enregistrements dans a qui n'a rien dans b?

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

Ou comme d'autres personnes sur ce fil dit:

select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null
66
albertein
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
15
Joseph Anderson

Une autre approche:

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

L'approche "existe" est utile s'il existe une autre clause "où" que vous devez associer à la requête interne.

5
Matt Hamilton
SELECT id FROM a
EXCEPT
SELECT a_id FROM b;
4
onedaywhen

select * from où ID n'est pas présent (sélectionnez a_id dans b)

2
BlackWasp

Vous obtiendrez probablement de bien meilleures performances (que d'utiliser «pas dans») si vous utilisez une jointure externe:

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

Dans le cas d'une jointure, c'est assez rapide, mais lorsque nous supprimons des enregistrements d'une base de données contenant environ 50 millions d'enregistrements et 4 jointures et plus en raison de clés étrangères, le processus prend quelques minutes. Où pas en état comme ça:

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)

Je peux également recommander cette approche pour la suppression si nous n’avons pas configuré la suppression en cascade . Cette requête ne prend que quelques secondes.

0
Petr Štipek

Une autre façon de l'écrire

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

Ouch, battu par Nathan :)

0
shahkalpesh

Cela vous protégera des valeurs NULL dans la clause IN, ce qui peut provoquer un comportement inattendu.

select * from où ID n'est pas présent (sélectionnez [a id] dans b où [a] n'est pas null )

0
Amy B

La première approche est

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

la deuxième approche est 

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

La première approche est très chère. La deuxième approche est meilleure.

Avec PostgreSql 9.4, j’ai utilisé la fonction "expliquer la requête" et la première requête avec un coût de coût = 0.00..1982043603.32 . À la place, la requête de jointure avec un coût de coût = 45946.77..45946.78

Par exemple, je recherche tous les produits qui ne sont compatibles avec aucun véhicule. J'ai 100 000 produits et plus de 1 million de compatibilités.

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

La requête de jointure a pris environ 5 secondes, mais la version de la sous-requête n’a jamais cessé au bout de 3 minutes.

0
Daniele Licitra