Sql 在具有Rails的树状结构中查找没有子节点的节点

Sql 在具有Rails的树状结构中查找没有子节点的节点,sql,ruby-on-rails,activerecord,Sql,Ruby On Rails,Activerecord,我有一个大致如下的树状结构: class Node < ActiveRecord::Base belongs_to :parent, :class_name => self.to_s, :foreign_key => 'parent_id' has_many :children, :class_name => self.to_s, :foreign_key => 'parent_id', :dependent => :destroy

我有一个大致如下的树状结构:

class Node < ActiveRecord::Base
   belongs_to :parent,   :class_name => self.to_s, :foreign_key => 'parent_id'
   has_many   :children, :class_name => self.to_s, :foreign_key => 'parent_id', :dependent => :destroy
   ...
end
但我还需要找到没有子节点但可以有父节点的节点,我很难找到它。我想我必须包括儿童活动,但是我迷路了,我不能使用:

named_scope, :faulty_not_parent, :include => :children, :conditions => "node.parent_id IS NULL"
明白了:

named_scope :not_parent, :conditions => "id NOT IN (SELECT DISTINCT parent_id FROM nodes WHERE parent_id IS NOT NULL)"
明白了:

named_scope :not_parent, :conditions => "id NOT IN (SELECT DISTINCT parent_id FROM nodes WHERE parent_id IS NOT NULL)"

我强烈建议您为此使用插件。我个人的建议是,只使用一列映射结构,而不是像嵌套的集合结构那样使用三列映射结构。

我强烈建议您为此使用插件。还有一些,我个人的建议是,只使用一列来映射结构,而不是像嵌套的集合结构那样使用三列。

我不是SQL专家,所以我想不出在纯SQL中实现这一点的好方法。当然,这意味着我也找不到使用命名的_作用域的方法。但您可以找到父节点,然后从所有节点中减去,如下所示:

def childless
 @childless ||= self.all - self.all(:joins => :children)
end

这并不像我想要的那么优雅,因为它需要在内存中加载很多内容。但它只需要2条select语句,这很好。我很想看看其他答案。

我不是SQL专家,所以我想不出一个在纯SQL中实现这一点的好方法。当然,这意味着我也找不到使用命名的_作用域的方法。但您可以找到父节点,然后从所有节点中减去,如下所示:

def childless
 @childless ||= self.all - self.all(:joins => :children)
end

这并不像我想要的那么优雅,因为它需要在内存中加载很多内容。但它只需要2条select语句,这很好。我有兴趣查看其他答案。

这是可行的,但我编辑了您的答案以搜索节点表,使其与您问题中的示例相匹配。这将避免与将来阅读此答案的人产生混淆。我的作用域自行工作,但在使用其他作用域时,我遇到了一个不明确的列名问题,必须在列名上更具体一点:named_scope:not_parent,:conditions=>nodes.id不在SELECT DISTINCT nodes.parent_id FROM nodes.parent_id不为null的节点中这起作用,但我编辑了您的答案以搜索nodes表,使其与问题中的示例匹配。这将避免与将来阅读此答案的人产生混淆。我的作用域自行工作,但在使用其他作用域时,我遇到了一个不明确的列名问题,必须在列名上更具体一点:named_scope:not_parent,:conditions=>nodes.id不在中从nodes.parent\u id不为NULL的节点中选择不同的nodes.parent\u id