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

¿Encontrar filas que tengan el mismo valor en una columna y otros valores en otra columna?

Este es un caso de división relacional . Hemos reunido un arsenal de técnicas bajo esta pregunta relacionada:

La dificultad especial es excluir usuarios adicionales. Hay básicamente 4 técnicas.

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

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

Ambas consultas no dependen de un UNIQUE restricción para (conversation_id, user_id) , que puede o no estar en su lugar. Es decir, la consulta incluso funciona si user_id 32 (o 3) aparece más de una vez para la misma conversación. Usted podría sin embargo, obtiene filas duplicadas en el resultado y necesita aplicar DISTINCT o GROUP BY .
La única condición es la que formulaste:

Consulta auditada

La consulta que vinculó en el comentario no funcionaría Olvidó excluir a otros participantes. Debería ser algo como:

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

Lo cual es similar a las otras dos consultas, excepto que no devolverá varias filas si user_id = 3 está vinculado varias veces.