【问题标题】:Can Rails 4 do nested queries with ActiveRecord?Rails 4 可以使用 ActiveRecord 进行嵌套查询吗?
【发布时间】:2019-08-30 13:05:11
【问题描述】:

我为我的 Rails 4 应用程序中的一些统计分析编写了一个新的 SQL 查询。出于可维护性、可读性和一致性的目的,我更希望它在 ActiveRecord 查询中而不是 SQL 中表达,但我不知道该怎么做。

我找到了一些使用嵌套 JOINs 的代码,但没有找到嵌套 SELECTs 的代码。

我有一个名为 groups 的表,它与 group_members 具有一对多关系(这些也是 ActiveRecord 对象 Group 和 GroupMember)。

我正在尝试计算所有成员计数中具有 X 数量成员的组数。这是用于显示有多少成员组的分布图。

这是我编写的查询,当前使用ActiveRecord::Base.connection.exec_query 运行:

SELECT members_count, COUNT(members_count) 
FROM (
      SELECT COUNT(*) AS members_count, "group_id" AS group_id 
      FROM "groups" 
      INNER JOIN "group_members" ON "group_members"."group_id" = "groups"."id" 
      GROUP BY "group_id"
     ) AS groups_count 
GROUP BY members_count 
ORDER BY members_count;

如何将其转换为 ActiveRecord 查询? 我要解决的问题是嵌套的 SELECT 调用。这可以在 Rails 4 的 ActiveRecord 中实现吗?

【问题讨论】:

  • 如果有帮助,这是正在生成的图表类型:imgur.com/a/JhEGTkp
  • 您可能想要研究的一种方法(略有不同并有一些注意事项)是counter cache

标签: sql ruby-on-rails postgresql ruby-on-rails-4 rails-activerecord


【解决方案1】:

恕我直言,将宝石留在您真正需要的时候。

您可以将子查询与fromselect 结合使用:

Group
  .from(
    Group
      .joins(:group_members)
      .select('COUNT(*) AS members_count, group_members.group_id')
      .group('group_members.group_id')
  )
  .select("members_count", 'COUNT(members_count)')
  .group("members_count")
  .order("members_count")

# SELECT "members_count", COUNT(members_count)
# FROM (
#   SELECT COUNT(*) AS members_count, group_members.group_id
#   FROM "groups"
#   INNER JOIN "group_members" ON "group_members"."group_id" = "groups"."id"
#   GROUP BY group_members.group_id
# ) subquery
# GROUP BY "members_count"
# ORDER BY "members_count" ASC

【讨论】:

  • 非常感谢!我不知道存在.from 方法。我不得不调整.joins,因为关联名为members,我想要一个内部连接。唯一的另一件事是外部组/顺序 - 使用符号语法意味着解析器尝试使用“groups.members_count”,所以我在所有外部语句中切换到使用“members_count”,这很有效。我将编辑您的帖子以明确说明
  • 当然,根据需要更新它以适应您的情况。很高兴为您提供帮助 (;
【解决方案2】:

我强烈建议不要使用 ORM,而转向类似 SQL 视图之类的东西。

有一个很棒的 gem 可以在 ruby​​ 中与 SQL 视图交互,称为 Scenic:https://github.com/scenic-views/scenic

性能是一个明显的原因,但我也认为您会发现在 SQL 中推理这类问题实际上更容易。 ActiveRecord 应该是一个工具,可以帮助您不必编写真正愚蠢的小查询,而不是从您的应用程序中完全消除原始 SQL。

话虽如此,select 可以处理与 ActiveRecord 中的join 相同的嵌套查询。

【讨论】:

  • 如果您想最大限度地使用 AR 并避免 sql 字符串修改(可能导致注入问题),请查看 ArelSqueel
  • 感谢七边大理石和加勒特。我将 ActiveRecord 答案标记为解决方案,因为它是我直接要求的,但这些宝石真的很有趣,我肯定会考虑我们如何进行此类查询。你在这里的推理绝对是对的,sevensidemarble - 我一直在编写 SQL,然后将其转换为 ActiveRecord 语法以用于许多这些统计查询
猜你喜欢
  • 2018-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
  • 2021-06-07
  • 1970-01-01
相关资源
最近更新 更多