PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Trovare righe che hanno lo stesso valore in una colonna e altri valori in un'altra colonna?

Questo è un caso di divisione relazionale . Abbiamo assemblato un arsenale di tecniche sotto questa domanda correlata:

La difficoltà particolare consiste nell'escludere utenti aggiuntivi. Ci sono fondamentalmente 4 tecniche.

Suggerisco 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;

Oppure 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)
   );

Entrambe le query non dipendono da un UNIQUE vincolo per (conversation_id, user_id) , che può essere o meno presente. Ciò significa che la query funziona anche se user_id 32 (o 3) è elencato più di una volta per la stessa conversazione. lo faresti ottieni righe duplicate nel risultato, tuttavia, e devi applicare DISTINCT o GROUP BY .
L'unica condizione è quella che hai formulato:

Query controllata

La query che hai collegato nel commento non funzionerebbe. Hai dimenticato di escludere altri partecipanti. Dovrebbe essere qualcosa del tipo:

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

Che è simile alle altre due query, tranne per il fatto che non restituirà più righe se user_id = 3 è collegato più volte.