Det här är ett fall av relationsdelning . Vi har samlat en arsenal av tekniker under denna relaterade fråga:
Den speciella svårigheten är att utesluta ytterligare användare. Det finns i princip fyra tekniker.
Jag föreslår 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;
Eller 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)
);
Båda frågorna inte beroende av en UNIQUE
begränsning för (conversation_id, user_id)
, som kanske är på plats eller inte. Det betyder att frågan fungerar även om user_id
32 (eller 3) listas mer än en gång för samma konversation. Du skulle få dubbletter av rader i resultatet, dock, och måste tillämpa DISTINCT
eller GROUP BY
.
Det enda villkoret är det du formulerade:
Reviderad fråga
frågan du länkade i kommentaren skulle inte fungera. Du glömde att utesluta andra deltagare. Borde vara något i stil med:
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)
);
Vilket liknar de andra två frågorna, förutom att det inte returnerar flera rader om user_id = 3
är länkad flera gånger.