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

PostgreSQL dove tutto è in array

Supponendo che la tabella di join segua le buone pratiche e abbia una chiave composta univoca definita, ovvero un vincolo per evitare righe duplicate, dovrebbe fare qualcosa come la seguente query semplice.

select conversation_id from conversations_users where user_id in (1, 2)
group by conversation_id having count(*) = 2

È importante notare che il numero 2 alla fine è la lunghezza dell'elenco di user_id. Questo ovviamente deve cambiare se l'elenco user_id cambia lunghezza. Se non puoi presumere che la tua tabella di join non contenga duplicati, cambia "count(*)" in "count(distinct user_id)" a un possibile costo in termini di prestazioni.

Questa query trova tutte le conversazioni che includono tutti gli utenti specificati anche se la conversazione include anche utenti aggiuntivi.

Se vuoi solo conversazioni con esattamente l'insieme di utenti specificato, un approccio consiste nell'utilizzare una sottoquery nidificata nella clausola where come di seguito. Nota, la prima e l'ultima riga sono le stesse della query originale, solo le due righe centrali sono nuove.

select conversation_id from conversations_users where user_id in (1, 2)
   and conversation_id not in
   (select conversation_id from conversations_users where user_id not in (1,2))
group by conversation_id having count(*) = 2

Allo stesso modo, puoi utilizzare un operatore di differenza di set se il tuo database lo supporta. Ecco un esempio nella sintassi Oracle. (Per Postgres o DB2, cambia la parola chiave "meno" in "tranne.)

select conversation_id from conversations_users where user_id in (1, 2)
  group by conversation_id having count(*) = 2
minus
  select conversation_id from conversations_users where user_id not in (1,2)

Un buon Query Optimizer dovrebbe tratta le ultime due variazioni in modo identico, ma controlla con il tuo database particolare per essere sicuro. Ad esempio, il piano di query Oracle 11GR2 ordina i due set di ID conversazione prima di applicare l'operatore meno, ma ignora il passaggio di ordinamento per l'ultima query. Quindi entrambi i piani di query potrebbero essere più veloci a seconda di molteplici fattori come il numero di righe, core, cache, indici ecc.