2013-08-15 4 views
0

j'existent pas dans un lien vers une autre table deux tables:requête postgresql pour sélectionner les lignes dans une table qui ne

Table "contact" 

id | customer_id 
----+------------- 
1 | 123 
2 | 123 
3 | 123 
4 | 888 

Et

Table "user_contact" 

user_id | contact_id 
--------+------------ 
456  | 1 
456  | 2 
789  | 3 
999  | 4 

Pour sélectionner tous les contacts qui ont un customer_id de 123 et existent dans user_contact avec un user_id de 456, je peux aller:

SELECT 
    contact.id 
FROM 
    contact JOIN user_contact ON 
     contact.id = user_contact.contact_id 
WHERE 
    contact.customer_id = 123 AND 
    user_contact.user_id = 456 

Comment puis-je sélectionner tous les contacts qui ont un customer_id de 123 mais ne pas existent dans user_contact avec un user_id de 456?

Essayer:

SELECT 
    contact.id 
FROM 
    contact JOIN user_contact ON 
     contact.id = user_contact.contact_id 
WHERE 
    contact.customer_id = 123 AND 
    user_contact.user_id != 456 

ne fonctionne évidemment pas comme il retourne une ligne pour chaque contact dans user_contact qui a un user_id = 456.

Répondre

3

Vous pouvez utiliser un simple LEFT JOIN et vérifiez que la la partie user_contact résultante n'existe pas (par exemple IS NULL);

SELECT c.* 
FROM contact c 
LEFT JOIN user_contact uc ON c.id = uc.contact_id AND uc.user_id='456' 
WHERE c.customer_id = '123' AND uc.contact_id IS NULL 

An SQLfiddle to test with.

+0

C'est ce que je cherchais, merci. –

1

Ceci est généralement mieux traité avec une sous-requête corrigée NOT EXISTS, car les performances ne dépendent pas tellement du nombre d'enregistrements enfants par parent.

SELECT c.* 
FROM contact c 
where c.customer_id = '123' and 
     not exists (
     select null 
     from user_contact uc 
     where c.id  = uc.contact_id and 
       uc.user_id = '456') 

Ceci utilisera une semi-jointure, qui s'arrête après avoir trouvé un seul enregistrement enfant.

Questions connexes