【问题标题】:Postgres database query to filter active record resultPostgres 数据库查询以过滤活动记录结果
【发布时间】:2016-06-06 13:33:57
【问题描述】:

我有三张桌子

  1. 公司
  2. 代码
  3. CompanyCode [join table] - 存储公司代码

现在,我想查找只有代码 2,3 和 5 的公司的记录。

我正在尝试

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

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

我希望拥有n_code235 的公司具有所有这三个值。

【问题讨论】:

  • 我对RoR不熟悉,但是在SQL中我相信你必须加入codes表3次。如果我错了,请纠正我。
  • @pumbo 你是,你可以做一个连接,并指定代码n_code的条件为2、3或5。
  • @j-dexx 请给我一个普通 SQL 的例子
  • @pumbo 我明白你现在的意思了。我以为你的意思是活动记录 .join 因为 Rails 关联 Rails 足够聪明,可以自动执行公司代码的连接,然后为你编码。
  • 您可以使用array_agg 为每个公司生成一个代码列表,然后过滤包含[2,3,5] 的数组

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


【解决方案1】:

之前的答案都不准确。如果您需要获取具有所有指定值但不只是某些值的记录,则不需要使用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 值聚合到一个数组中(请注意,查询是按公司分组的)并检查它是否包含右侧的数组(包含所有它的值)。

【讨论】:

    【解决方案2】:

    你可以这样做:

    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,3,5] 的公司不仅是 2。您的回答会给我代码为 2 的公司。
    • 不应该这样。您是否测试过代码并阅读了完整的说明?
    • .having('count(*) = ?', required_codes.count) - 请解释这些。我已经阅读了你的解释。但你的代码没有给我任何结果。
    • 在您的情况下,这意味着该组应该与 required_codes 数组具有相同的计数,即 3。
    • Company.joins(:codes) .where(codes: { n_code: required_codes }) -> 这个结果是 56 个公司。但在按公司 ID 分组后,代码计数 = 3 。结果没有。但是有 3 个代码的公司可用。
    【解决方案3】:

    让我们这样查询:

    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 只获取包含所有required_codescompany_id,并且分组后的不同代码必须等于required_codes
    • 有了company_id之后,我们就可以轻松查询Company

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 2014-05-31
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      相关资源
      最近更新 更多