Rails - 仅查找存在has_many关联记录的记录

时间:2016-02-19 14:59:56

标签: ruby-on-rails ruby-on-rails-3 postgresql activerecord

我有一个与has_many关系的模型与另一个模型如此:

class Parent < ActiveRecord::Base
  has_many :children
end

class Child < ActiveRecord::Base
  belongs_to :parent
end

由于有些父母可能没有孩子,我想做一个只返回有孩子的父母的查询。我怎么会这样做?

由于我在Rails 3上执行此操作,如果此查询不使用where.not.语法,将会很有帮助。

4 个答案:

答案 0 :(得分:12)

Rails 4

Parent.includes(:children).where.not(children: {id: nil})

Parent.joins(:children).where.not(children: {id: nil}).distinct

Rails 3

Parent.joins(:children).where('children.id NOT NULL').distinct

答案 1 :(得分:2)

可以使用SQL语法

完成
Parent.where('id IN (SELECT DISTINCT(parent_id) FROM children')

或者,为了保持DRY,可以在范围内使用:

class Parent < ActiveRecord::Base
  has_many :children

  scope :with_children, where('id IN (SELECT DISTINCT(parent_id) FROM children')
end

然后你可以找到有孩子的父母:

Parent.with_children

答案 2 :(得分:0)

where.related (Rails 7+)

Rails 7 引入了一种检查关联是否存在的新方法 - where.associated

请看下面的代码片段:

# Before:
account.users.joins(:contact).where.not(contact_id: nil)

# After:
account.users.where.associated(:contact)

这是一个在后台使用的 SQL 查询示例:

Post.where.associated(:author)
# SELECT "posts".* FROM "posts"
# INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
# WHERE "authors"."id" IS NOT NULL

因此,您的特定案例可以改写如下:

Parent.where.associated(:child)

谢谢。

来源:

注意事项:

答案 3 :(得分:-2)

类似于Wes&#39;回答,但保持有点害羞的SQL语法:

Parent.find(Child.all.map{|c|c.parent_id}.uniq)

这一位:

Child.all.map{|c|c.parent_id}.uniq

为您提供了一个parent_id数组(使用.uniq删除了dupes)。

从那里,它是一个简单的.find。或者,如果您愿意,请使用.where