結合テーブルが適切な方法に従っており、一意の複合キーが定義されていると仮定します。つまり、行の重複を防ぐための制約がある場合は、次の簡単なクエリのようになります。
select conversation_id from conversations_users where user_id in (1, 2)
group by conversation_id having count(*) = 2
最後の2は、user_idのリストの長さであることに注意してください。 user_idリストの長さが変更された場合は、明らかに変更する必要があります。結合テーブルに重複が含まれていないと想定できない場合は、パフォーマンスをいくらか犠牲にして、「count(*)」を「count(distinctuser_id)」に変更してください。
このクエリは、たとえであっても、指定されたすべてのユーザーを含むすべての会話を検索します 会話には追加のユーザーも含まれます。
正確にとの会話のみが必要な場合 指定されたユーザーのセットの場合、1つのアプローチは、以下のようにwhere句でネストされたサブクエリを使用することです。最初と最後の行は元のクエリと同じであり、真ん中の2行だけが新しいことに注意してください。
select conversation_id from conversations_users where user_id in (1, 2)
and conversation_id not in
(select conversation_id from conversations_users where user_id not in (1,2))
group by conversation_id having count(*) = 2
同様に、データベースでサポートされている場合は、差セット演算子を使用できます。 Oracle構文の例を次に示します。 (PostgresまたはDB2の場合、キーワード「マイナス」を「例外」に変更します。)
select conversation_id from conversations_users where user_id in (1, 2)
group by conversation_id having count(*) = 2
minus
select conversation_id from conversations_users where user_id not in (1,2)
優れたクエリオプティマイザはすべき 最後の2つのバリエーションは同じように扱いますが、特定のデータベースで確認してください。たとえば、Oracle 11GR2クエリ・プランは、マイナス演算子を適用する前に2セットの会話IDをソートしますが、最後のクエリのソート・ステップをスキップします。したがって、行数、コア、キャッシュ、インデックスなどの複数の要因に応じて、どちらのクエリプランも高速になる可能性があります。