sql >> Base de Datos >  >> RDS >> PostgreSQL

PostgreSQL donde todo en matriz

Suponiendo que la tabla de unión sigue las buenas prácticas y tiene definida una clave compuesta única, es decir, una restricción para evitar filas duplicadas, entonces debería funcionar algo como la siguiente consulta simple.

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

Es importante tener en cuenta que el número 2 al final es la longitud de la lista de user_ids. Obviamente, eso debe cambiar si la lista user_id cambia de longitud. Si no puede suponer que su tabla de unión no contiene duplicados, cambie "count(*)" a "count(distinct user_id)" con algún costo posible en el rendimiento.

Esta consulta encuentra todas las conversaciones que incluyen a todos los usuarios especificados incluso si la conversación también incluye usuarios adicionales.

Si solo desea conversaciones con exactamente el conjunto especificado de usuarios, un enfoque es usar una subconsulta anidada en la cláusula where como se muestra a continuación. Tenga en cuenta que la primera y la última línea son las mismas que las de la consulta original, solo las dos líneas del medio son nuevas.

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

De manera equivalente, puede usar un operador de diferencia establecida si su base de datos lo admite. Aquí hay un ejemplo en la sintaxis de Oracle. (Para Postgres o DB2, cambie la palabra clave "menos" a "excepto".)

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 buen optimizador de consultas debería trate las dos últimas variaciones de manera idéntica, pero verifique con su base de datos particular para estar seguro. Por ejemplo, el plan de consulta Oracle 11GR2 ordena los dos conjuntos de ID de conversación antes de aplicar el operador menos, pero omite el paso de ordenación para la última consulta. Por lo tanto, cualquiera de los planes de consulta podría ser más rápido dependiendo de múltiples factores, como la cantidad de filas, núcleos, caché, índices, etc.