Postgres数据库查询以过滤活动记录结果

时间:2016-02-24 10:12:25

标签: ruby-on-rails ruby database postgresql ruby-on-rails-4

我有三张桌子

  1. 公司
  2. CompanyCode [join table] - 存储公司代码
  3. 现在,我想找到只有代码2,3和5的公司的记录。

    我正在尝试

    Comapny.joins(:codes).where('codes.n_code' IN ? , [2,3,5])
    

    但这会导致所有公司只有n_code = 2n_code = 3n_code = 5

    我希望公司n_code 235具有这三个值。

3 个答案:

答案 0 :(得分:2)

之前的答案都不准确。如果您需要获取具有所有指定值但不仅包含某些值的记录,则不需要使用WHERE n_code IN (2,3,5)条件,因为它将获取至少包含其中一个值的所有记录,但不是所有人都在同一时间。此外,如前所述,附加条件HAVING count(codes.n_code) = 3不是解决方案,因为它不能保证这3个值实际上是2,3和5。

我不擅长Ruby,所以我将在普通SQL中给你一个例子,说明如何获得具有所有值的记录:

SELECT company_codes.company_id
FROM company_codes
JOIN codes ON codes.id = company_codes.code_id
GROUP BY company_codes.company_id
HAVING array_agg(codes.n_code) @> ARRAY[2, 3, 5]

工作原理:在HAVING部分中,您将公司的所有n_code值聚合到一个数组中(请注意,查询按公司分组)并检查它是否包含右侧的数组(包含其所有值)。

答案 1 :(得分:1)

你可以这样做:

required_codes = [2, 3, 5]

Company.joins(:codes)
       .where(codes: { n_code: required_codes })
       .group('companies.id')
       .having('count(*) = ?', required_codes.count)

根据你的表和字段命名,你的group子句可能看起来有点不同。

它的作用是:

  • 获取所有拥有代码的公司
  • ,其中包含一个必需的代码
  • 对它们进行分组,以便当文章有代码2,3,5时我们有一组3,或者当文章有标签2,3和6时,我们有一组2。
  • 然后只使用我们所需代码数组中指定的成员数量的那些组。

答案 2 :(得分:0)

让我们这样做:

required_codes = [2, 3, 5]

sub_query = %Q{
  SELECT company_codes.company_id
  FROM company_codes
  JOIN codes
  ON codes.id = company_codes.code_id
  WHERE codes.n_code IN (#{required_codes.join(',')})
  GROUP BY company_codes.company_id
  HAVING COUNT(DISTINCT codes.n_code) = #{required_codes.size}
}

Company.where("id IN (#{sub_query})"

说明:

  • sub_query只会得到company_id,其中包含所有required_codes,并且分组后的不同代码必须等于required_codes
  • 拥有company_id后,我们可以轻松查询Company