次のように、同じモデルでレコードを保持する 2 つのリレーションがあるとします。
@companies1 = Company.where(...)
@companies2 = Company.where(...)
これら 2 つの関係の交点、つまり、両方の関係にある会社のみを見つけるにはどうすればよいですか?
次のように、同じモデルでレコードを保持する 2 つのリレーションがあるとします。
@companies1 = Company.where(...)
@companies2 = Company.where(...)
これら 2 つの関係の交点、つまり、両方の関係にある会社のみを見つけるにはどうすればよいですか?
デフォルトでは、これらwhere
を一緒に接続すると AND が作成されますが、これはあなたが望むものです。
多くは次のとおりです。
class Company < ActiveRecord::Base
def self.where_1
where(...)
end
def self.where_2
where(...)
end
end
@companies = Company.where_1.where_2
====== 更新 ======
次の 2 つのケースがあります。
# case 1: the fields selecting are different
Company.where(:id => [1, 2, 3, 4]) & Company.where(:other_field => true)
# a-rel supports &, |, +, -, but please notice case 2
# case 2
Company.where(:id => [1, 2, 3]) & Company.where(:id => [1, 2, 4, 5])
# the result would be the same as
Company.where(:id => [1, 2, 4, 5])
# because it is &-ing the :id key, instead of the content inside :id key
したがって、ケース 2 の場合は、@apneadiving がコメントしたようにする必要があります。
Company.where(...).all & Company.where(...).all
もちろん、これを行うと 2 つのクエリが送信され、おそらく必要以上の結果がクエリされます。
SQL キーワード INTERSECT を使用します。
params1 = [1,2,4]
params2 = [1,3,4]
query = "
SELECT companies.* FROM companies
WHERE id in (?,?,?)
INTERSECT
SELECT companies.* FROM companies
WHERE id in (?,?,?)
"
Company.find_by_sql([query, *params1, *params2])
以前のソリューションよりも高速になります。
あなたが使用することができますActiveRecord::SpawnMethods#merge
例:
Company.where(condition: 'value').merge(Company.where(other_condition: 'value'))