Toto je případ relačního rozdělení . V rámci této související otázky jsme sestavili arzenál technik:
Zvláštním problémem je vyloučení dalších uživatelů. V zásadě existují 4 techniky.
Navrhuji 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;
Nebo 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)
);
Oba dotazy ne závisí na UNIQUE omezení pro (conversation_id, user_id) , který může a nemusí být na místě. To znamená, že dotaz funguje i když user_id 32 (nebo 3) je uveden více než jednou pro stejnou konverzaci. by jste získat duplicitní řádky ve výsledku a je třeba použít DISTINCT nebo GROUP BY .
Jediná podmínka je ta, kterou jste formulovali:
Auditovaný dotaz
dotaz, který jste propojili v komentáři by nefungovalo. Zapomněli jste vyloučit ostatní účastníky. Mělo by to být něco jako:
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)
);
Což je podobné jako u dalších dvou dotazů, kromě toho, že nevrátí více řádků, pokud user_id = 3 je propojen vícekrát.