【问题标题】:Rails includes() LEFT OUTER JOIN with custom ON clauseRails includes() 带有自定义 ON 子句的 LEFT OUTER JOIN
【发布时间】:2014-03-14 05:37:31
【问题描述】:

在我的场景中,我有一个 BlogPost 模型 has_and_belongs_to_many :categories。我想过滤 out 属于特定类别的博客文章,同时仍然允许未分类的博客文章(因此需要 LEFT OUTER JOIN)。

我希望这会起作用:

BlogPost.active.includes(:categories).where.not(categories: { id: [1, 2, 3] })

但它没有正确过滤,因为它将条件放在查询的末尾,在 LEFT OUTER JOIN 之外(原因请参见这个 SO 问题/答案:SQL join: where clause vs. on clause


这可行,但很难看:

BlogPost.active.joins("LEFT OUTER JOIN blog_posts_categories
      ON blog_posts_categories.blog_post_id = blog_posts.id
      AND blog_posts_categories.category_id NOT IN(1, 2, 3)")

是否有一种 ActiveRecord 友好的方式可以将条件添加到 LEFT OUTER JOIN 的 ON 子句,而无需像我那样手动输入?

【问题讨论】:

  • 如果您想过滤掉博客文章,为什么要使用 LEFT JOIN 或 includes?为什么不是标准的 JOIN (joins)?
  • @PinnyM 一个标准的 JOIN 对我不起作用,因为我需要查询返回可能没有任何类别标记的博客帖子
  • @ncherro 一旦您提及关联的主键和外键,它将自动使用。

标签: sql ruby-on-rails activerecord join rails-activerecord


【解决方案1】:

我认为这可能有效。

BlogPost.active.joins(:categories).merge(Category.where.not(categories: { id: [1,2,3] })

并将它与一个范围一起添加,该范围可以获取所有没有类别的博客文章。另一个想法是改用has_many through 关系,并实际为BlogPostCategory 创建一个模型,因为您可以在其上添加中间范围。

【讨论】:

  • 谢谢,但您的第一个建议会产生 INNER JOIN,这对我不起作用。我没想过将其转换为has_many_through 关系。如果可行,我会再次回复
  • 还有left_outer_joins on is:ActiveRecord::QueryMethods,所以也许你正在寻找BlogPost.active.left_outer_joins(:categories).merge(Category.where.not(categories: { id: [1,2,3] })
【解决方案2】:

我对 ActiveRecord 语法并不十分熟悉,但您能否扩展过滤器以包含 category_id IS NULL 的行?这将满足您的要求。

【讨论】:

    猜你喜欢
    • 2011-01-30
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 2014-07-14
    • 2012-02-04
    • 1970-01-01
    相关资源
    最近更新 更多