简体   繁体   English

Rails 包含()LEFT OUTER JOIN 与自定义 ON 子句

[英]Rails includes() LEFT OUTER JOIN with custom ON clause

In my scenario, I have a BlogPost model that has_and_belongs_to_many :categories .在我的场景中,我有一个BlogPost模型has_and_belongs_to_many :categories I want to filter out Blog Posts that belong to specific Categories, while still allowing for uncategorized Blog Posts (hence the need for a LEFT OUTER JOIN).我想筛选属于特定的类别,同时仍允许未分类的博客文章(因此需要一个LEFT OUTER JOIN)博客文章。

I expected this to work:我希望这能奏效:

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

But it doesn't filter correctly because it puts the conditions at the end of the query, outside the LEFT OUTER JOIN (see this SO question / answer for the reason: SQL join: where clause vs. on clause )但它没有正确过滤,因为它将条件放在查询的末尾,在 LEFT OUTER JOIN 之外(请参阅此 SO 问题/答案以了解原因: SQL join: where clause vs. on clause


This works, but it is ugly:这有效,但很丑陋:

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)")

Is there an ActiveRecord-friendly way to add conditionals to the ON clause of a LEFT OUTER JOIN without manually typing it out the way I did?是否有一种 ActiveRecord 友好的方法可以将条件添加到 LEFT OUTER JOIN 的 ON 子句中,而无需像我那样手动输入?

I think this might work.我认为这可能会奏效。

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

and add it together with a scope that gets all the blogposts without a category.并将它与一个范围添加在一起,该范围可以获取所有没有类别的博客文章。 Another thought would be to instead use a has_many through relationship, and actually create a model for BlogPostCategory as you can add intermediate scopes on it.另一个想法是使用has_many through关系,实际上为BlogPostCategory创建一个模型,因为您可以在其上添加中间范围。

I'm not thoroughly familiar with ActiveRecord syntax, but can you extend the filter to include rows where category_id IS NULL ?我对 ActiveRecord 语法不是很熟悉,但是您能否扩展过滤器以包含 category_id 为IS NULL行? That will satisfy your requirement.那将满足您的要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM