说我有,在同一个模型保持记录的两种关系,如:交叉的两个关系
@companies1 = Company.where(...)
@companies2 = Company.where(...)
我如何才能找到这两种关系的交叉点,即只存在中同时这些公司?
说我有,在同一个模型保持记录的两种关系,如:交叉的两个关系
@companies1 = Company.where(...)
@companies2 = Company.where(...)
我如何才能找到这两种关系的交叉点,即只存在中同时这些公司?
默认情况下,将这些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
====== UPDATED ======
有两种情况:
# 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
当然,这样做会发出两个查询,并且很可能会查询比您需要的更多结果。
使用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])
它会比以前的解决方案更快。
我解决类似的问题,这样
Company.connection.unprepared_statement do
Company.find_by_sql "#{@companies1.to_sql} INTERSECT #{@companies2.to_sql}"
end
我们需要在这里unprepared_statement
块,因为最新的Rails版本使用准备好的发言加快AREL查询,但我们需要的地方纯SQL。
你可以使用ActiveRecord::SpawnMethods#merge
例子:
Company.where(condition: 'value').merge(Company.where(other_condition: 'value'))
它只是增加了一个where条件。它不适用于INTERSECT –
看来你不希望这里的SQL。因此,您可以使用数组交集方法:http://www.ruby-doc.org/core/classes/Array.html#M000274 – apneadiving