PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Trouver des lignes qui ont la même valeur dans une colonne et d'autres valeurs dans une autre colonne ?

C'est un cas de division relationnelle . Nous avons rassemblé un arsenal de techniques sous cette question connexe :

La difficulté particulière est d'exclure des utilisateurs supplémentaires. Il existe essentiellement 4 techniques.

Je suggère LEFT JOIN / IS NULL :

SELECT cu1.conversation_id
FROM        conversation_user cu1
JOIN        conversation_user cu2 USING (conversation_id)
LEFT   JOIN conversation_user cu3 ON cu3.conversation_id = cu1.conversation_id
                                 AND cu3.user_id NOT IN (3,32)
WHERE  cu1.user_id = 32
AND    cu2.user_id = 3
AND    cu3.conversation_id IS NULL;

Ou NOT EXISTS :

SELECT cu1.conversation_id
FROM   conversation_user cu1
JOIN   conversation_user cu2 USING (conversation_id)
WHERE  cu1.user_id = 32
AND    cu2.user_id = 3
AND NOT EXISTS (
   SELECT 1
   FROM   conversation_user cu3
   WHERE  cu3.conversation_id = cu1.conversation_id
   AND    cu3.user_id NOT IN (3,32)
   );

Les deux requêtes ne le font pas dépendent d'un UNIQUE contrainte pour (conversation_id, user_id) , qui peut ou non être en place. Cela signifie que la requête fonctionne même si user_id 32 (ou 3) est répertorié plus d'une fois pour la même conversation. Vous le feriez obtenir des lignes en double dans le résultat, cependant, et besoin d'appliquer DISTINCT ou GROUP BY .
La seule condition est celle que vous avez formulée :

Requête auditée

La requête que vous avez liée dans le commentaire ne fonctionnerait pas. Vous avez oublié d'exclure d'autres participants. Devrait être quelque chose comme :

SELECT *  -- or whatever you want to return
FROM   conversation_user cu1
WHERE  cu1.user_id = 32
AND    EXISTS (
   SELECT 1
   FROM   conversation_user cu2
   WHERE  cu2.conversation_id = cu1.conversation_id 
   AND    cu2.user_id = 3
   )
AND NOT EXISTS (
   SELECT 1
   FROM   conversation_user cu3
   WHERE  cu3.conversation_id = cu1.conversation_id
   AND    cu3.user_id NOT IN (3,32)
   );

Ce qui est similaire aux deux autres requêtes, sauf qu'il ne renverra pas plusieurs lignes si user_id = 3 est lié plusieurs fois.