我发现了一个answer,它有一些有用的having
示例,用于查找具有n
孩子的父母,但同样不能用于查找没有孩子的父母(可能是因为连接排除了他们)。
scope :with_children, joins(:children).group("child_join_table.parent_id").having("count(child_join_table.parent_id) > 0")
有谁能给我指个方向吗?
发布于 2013-08-06 21:51:56
Rails 3和4
scope :without_children, includes(:children).where(:children => { :id => nil })
这里最大的区别是包含变成了一个包含:一个包含加载所有的关系,如果它们存在,joins
将只加载相关的对象,而忽略没有关系的对象。
事实上,scope :with_children, joins(:children)
应该足以返回至少有一个子代的父代。试试看!
Rails 5
请看下面@Anson的答案
对于Rails4.1到6.0,activerecord_where_assoc
gem都可以做到这一点。
scope :without_children, where_assoc_not_exists(:children)
自引用关系被无缝地处理。
这也避免了诸如joins
使查询返回单个记录的多行之类的问题。
正如@MauroDias指出的那样,如果你的父母和孩子之间是一个自我引用的关系,上面的代码将不会工作。
通过一些研究,我发现了如何做到这一点:
考虑这个模型:
class Item < ActiveRecord::Base
has_many :children, :class_name => 'Item', :foreign_key => 'parent_id'
如何返回没有子项的所有项(Ren):
Item.includes(:children).where(children_items: { id: nil })
我是怎么找到那个children_items
表的?
Item.joins(:children)
生成以下SQL:
SELECT "items".*
FROM "items"
INNER JOIN "items" "children_items"
ON "children_items"."parent_id" = "items"."id"
因此,我猜测Rails在自引用情况下需要连接时会使用表。
类似问题:
发布于 2016-11-10 00:04:03
@MrYoshiji有一个可靠的Rails 4答案,但对于那些使用Rails 5的人来说,你有更多的选择。
使用Rails 5的:
从Rails5开始,您还可以使用left_outer_joins来避免加载关联。它是在拉取请求#12071中引入的。
scope :without_children, -> { left_outer_joins(:children).where(children: { id: nil }) }
对于有孩子的父母,MrYoshiji先生的Rails 4解决方案仍然是可以使用的:
scope :with_children, -> { joins(:children).uniq }
发布于 2018-05-29 20:02:41
这就是我为Rails5解决这个问题的方法:
scope :without_comments, -> do
left_outer_joins(:comments).where(comments: { id: nil })
end
https://stackoverflow.com/questions/18082096
复制相似问题