mysql - Rails 与连接表相交查询

标签 mysql ruby-on-rails-3

在我的 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 个结果。

如果您想以优化的方式进行操作,这将比您最初想象的要复杂一些。

您需要将 universities 表两次连接到您的 advisors 表,然后分别将条件应用于每个连接表。以下应该有效:

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")

我会选择 top 方法。

你也可以用未优化的方式来做,也许让代码更易读:

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/

相关文章:

javascript - 创建另一个帐户后显示失败 "Sorry, your registration failed. Please go back and try again."

mysql - Where 子句为每个 ID 最多选择两条记录

mysql - 从laravel 4中的json数组获取元素

mysql - 这条SQL中的 "t"指的是什么?

ruby - Rails 子域不起作用

ruby-on-rails-3 - javascript_include_tag :defaults does not work

javascript - Rails 3 - 应用程序布局问题

ruby-on-rails - :disabled field not working in fields_for

php - session 中突然出现 undefined variable 而不进行任何更改

ruby - 地理编码器 Gem : Unable to reverse geocode certain Google Map results