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.