これは、ネストされたサブクエリを使用して実行できます。これは実用的なソリューションですが、必ずしも効率的なソリューションではないため、いくつかのベンチマークを実行する必要があります。
A
以下は、との間のjoin_tableで実行される3つのネストされたクエリを含みますB
。最初に、またはのいずれでもないすべてのID B
(これらを呼び出しますexcluded_bs
)を決定します。次に、これらと関係があるものを判別し、それらを呼び出します。含まれていないすべての'は、まさに私たちが望むものです(それらを呼び出します)。テーブルをクエリした後。B1
B2
A
excluded_bs
excluded_as
A
excluded_as
included_as
included_as
A
excluded_bs = %(SELECT B_id FROM join_table WHERE B_id NOT IN (:included_bs))
excluded_as = %(SELECT A_id FROM join_table WHERE B_id IN (#{excluded_bs}))
included_as = %(SELECT A_id FROM join_table WHERE A_id NOT IN (#{excluded_as}))
A.where("id IN (included_as)", :included_bs => [B1.id, B2.id])
これにより、正確にA
ととの関係にあるすべての'が得られますが、他のとは関係がありません。これを少しクリーンアップしてより効率的にすることができるかもしれませんが、少なくとも機能するはずです。B1
B2
編集:
おっと!B1
またはのいずれかのみを持つものを削除するにはB2
、を試してくださいGROUP BY
。最後のサブクエリをに変更します
included_as = %(SELECT A_id, COUNT(*) as Total FROM join_table WHERE A_id NOT IN (#{excluded_as}) GROUP BY A_id HAVING Total = :count)
との主なクエリ
Bs = [B1, B2]
A.where("id IN (SELECT A_id FROM (#{included_as}))", :included_bs => Bs.map(&:id), :count => Bs.count)