在我的Rails 3.2应用程序中,有一个AttendedUniversity
模型,其中包含以下字段:
university_name
major_name
university_type # 0 for undergrad and 1 for graduate
advisor_id # for the Advisor model
Advisor
模型具有许多attended_universities
,并且attended_university
属于advisor
。我想找一位具有一定本科生和一定毕业经历的顾问,例如本科生专业1,研究生专业2。
我尝试了以下方法:
Advisor.includes(:attended_universities).
where("attended_universities.university_name = 'university1' AND
attended_universities.major_name = 'major1' AND
attended_universities.university_type = 0").
where("attended_universities.university_name = 'university2' AND
attended_universities.major_name = 'major2' AND
attended_universities.university_type = 1")
上面给了我空虚的结果,当它不应该的时候。
最佳答案
您要与查询匹配的是,该行中的每所大学都应使用名称'university1'
和名称'university2'
。
对于其他情况,正在执行类似的检查。由于表格中没有一个大学行会包含两个名称,两个专业或两种类型,因此将为您提供0个结果。
如果您想以最佳方式进行操作,这将比您最初想的要复杂一些。
您将需要将大学表两次连接到顾问表,然后将条件分别应用于每个联接表。以下应该工作:
joins_str = ->(tn) do
"INNER JOIN attended_universities AS #{tn} ON #{tn}.advisor_id = advisors.id"
end
criteria_one = {name: 'university1',
major_name: 'major1',
university_type: 0}
criteria_two = {name: 'university2',
major_name: 'major2',
university_type: 1}
Advisor.
joins(joins_str.call('au_one')).
joins(joins_str.call('au_two')).
where(au_one: criteria_one).
where(au_two: criteria_two).
group("advisors.id")
我会采用顶级方法。
您也可以采用未优化的方式进行操作,也许会使代码更具可读性:
advisors_with_unis = Advisor.joins(:attended_universities)
# fetch advisor ids that fulfill criteria_one
ids_one = advisors_with_unis.
where(attended_universities: criteria_one).
pluck("DISTINCT advisors.id")
# fetch advisor ids that fulfill criteria_two
ids_two = advisors_with_unis.
where(attended_universities: criteria_two).
pluck("DISTINCT advisors.id")
# get intersection of both id arrays
ids = ids_one & ids_two
# get advisors
Advisor.where(id: ids)
另一个解决方案是从数据库中获取所有记录,然后使用Ruby进行过滤:
def university_matches?(uni, name, major, uni_type)
uni.name == name &&
uni.major_name == major &&
uni.university_type == uni_type
end
Advisor.includes(:attended_universities).select do |advisor|
universities = advisor.attended_universities
universities.any? do |uni|
university_matches?(uni, 'university1', 'major1', 0)
end &&
universities.any? do |uni|
university_matches?(uni, 'university2', 'major2', 1)
end
end
如前所述,我会选择第一个。
关于mysql - Rails相交查询与联接表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29187824/