users
テーブルもあると仮定します。
SELECT id
FROM conversations AS c
WHERE NOT EXISTS
( SELECT *
FROM users AS u
WHERE u.id IN (1, 2, 3, 4)
AND NOT EXISTS
( SELECT *
FROM conversations_users AS cu
WHERE cu.user = u.id
AND cu.conversation = c.id
)
)
AND NOT EXISTS
( SELECT *
FROM conversations_users AS co -- and only them
WHERE co.conversation = c.id
AND co.user NOT IN (1, 2, 3, 4)
) ;
テーブルを持っていないusers
か、使いたくない場合 (理由はわかりますがとにかく)、この部分を置き換えることができます。
WHERE NOT EXISTS
( SELECT *
FROM users AS u
WHERE u.id IN (1, 2, 3, 4)
AND NOT EXISTS
と:
WHERE NOT EXISTS
( SELECT *
FROM (SELECT 1 AS id UNION SELECT 2 UNION
SELECT 3 UNION SELECT 4) AS u
WHERE NOT EXISTS
上記のクエリは一般的なものですが、MySQL ではあまり効率的ではありません (二重のネストと単純なオプティマイザーのせいです)。このGROUP BY / COUNT
方法はおそらくより効率的なレベルですが、データでテストしてください。また、この種の質問に答える方法は他にも (10 以上) あります。この回答では、次の回答を参照してください: How to filter SQL results in has-many-through relationship そこにあるクエリ 5 と 6 は、MySQL で非常に効率的であると期待しています (group by クエリよりも効率的なレベルです)。
あなたのケースには違いがあります。質問/回答は(単純な)関係分割についてですが、正確な関係分割が必要なので、次のように5を書くことができます:
SELECT id
FROM conversations AS c
WHERE EXISTS (SELECT * FROM conversations_users AS cu
WHERE cu.conversation = c.id AND cu.user = 1)
AND EXISTS (SELECT * FROM conversations_users AS cu
WHERE cu.conversation = c.id AND cu.user = 2)
AND EXISTS (SELECT * FROM conversations_users AS cu
WHERE cu.conversation = c.id AND cu.user = 3)
AND EXISTS (SELECT * FROM conversations_users AS cu
WHERE cu.conversation = c.id AND cu.user = 4)
AND NOT EXISTS (SELECT * FROM conversations_users AS cu
WHERE cu.conversation = c.id AND cu.user NOT IN (1,2,3,4))