【问题标题】:JOIN ON ... AND conditions when eager loading association in ActiveRecordJOIN ON ... AND 在 ActiveRecord 中急切加载关联时的条件
【发布时间】:2016-02-16 09:59:48
【问题描述】:

请注意,这不是关于向关联添加 WHERE 条件的问题,而是关于在使用 eager_load 时如何更改 JOIN 子句的相当高级的问题。

假设我有这些模型

class Parent
  has_many :children
  have_many :grades, through: :children
end

class Child
  belongs_to :parent
end

class Grade
  belongs_to :child
end

所以要急切地加载我会做的父母:

Parent.eager_load(:grades)

但如果我想要所有的父母 - 但只是像这样急切地加载最高得分:

LEFT OUTER JOIN grades ON grades.child_id = children.id AND grades.level = 'A+'

我尝试过使用includes(:children).joins("LEFT OUTER JOIN grades ON grades.child_id = children.id AND grades.level = 'A+'"),但由于 Rails 不构建关联对象,它会导致对每个父对象进行额外查询。

我没有找到任何关于将 eager_load 与自定义 SQL 字符串一起使用的参考资料,并且在没有更明智的情况下使用 dug through the source

【问题讨论】:

  • 这不是针对实际应用程序,而是出于好奇,如果可能的话。

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


【解决方案1】:

如果我是对的,您只想预先加载关联的子集。好吧,为了做到这一点,您需要智取 rails 。您基本上可以使用 ruby​​ lambda 中的 where 子句创建另一个关联,例如“highest_grade”来获取 A+ 级的成绩。这可以通过使用下面的sn-p代码来实现

class Parent
  has_many :children
  has_many :grades, through: :children
  has_many :highest_grade, ->{where(level: 'A+')}, class_name: "Grade", through: :children
end

现在您需要预先加载最高等级的关联。

 Parent.eager_load(:highest_grades)

这实际上将加载所有父母以及仅那些等级为 A+ 的成绩。

它会生成以下查询。

 SQL (0.3ms)  SELECT `parents`.`id` AS t0_r0, `parents`.`created_at` AS    t0_r1, `parents`.`updated_at` AS t0_r2, `grades`.`id` AS t1_r0,    `grades`.`child_id` AS t1_r1, `grades`.`created_at` AS t1_r2, `grades`.`updated_at` AS t1_r3, `grades`.`level` AS t1_r4 FROM `parents` LEFT OUTER JOIN `children` ON `children`.`parent_id` = `parents`.`id` LEFT OUTER JOIN `grades` ON `grades`.`child_id` = `children`.`id` AND `grades`.`level` = '

如果您想了解这是如何工作的。请使用this link as a reference

【讨论】:

    【解决方案2】:

    编辑

    这并不能解决上述问题。


    您不能随意更改调用eager_load 生成的JOIN。 WHERE 子句是您唯一的选择,它与您的 JOIN 条件具有完全相同的效果。在这里,即使你不想要它:

    Parent.eager_load(:grades).where("grades.level = 'A+'")
    

    【讨论】:

    • 不。 where 子句适用于整个查询,因此它不会包括没有 a+ 成绩的父母。这就是我使用左外连接的原因。
    • 嗯,我得试试那个。谢谢
    • 对不起,我删除了我的最后一条评论,因为我意识到它仍然没有满足您的需求
    • 看起来不可能。我很想知道你能不能弄明白。
    猜你喜欢
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多