【问题标题】:Find user who has no post in Rails查找在 Rails 中没有帖子的用户
【发布时间】:2014-09-12 16:54:22
【问题描述】:

这是数据库关系:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
end

我遇到了一个功能,我想查询所有还没有任何帖子的用户。我知道我们可以这样做:

users = User.all
users.each do |user|
  unless user.posts.any?
    # do something when user don't have any post.
  end
end

但是,我想知道是否有任何方法可以通过仅使用一个查询来优化这一点。

谢谢!

【问题讨论】:

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


    【解决方案1】:

    这会产生一个查询,该查询会获取所有还没有帖子的用户:

    User.includes(:posts).references(:posts).where('posts.id IS NULL')
    

    另一个解决方案是这样的:

    User.where('NOT EXISTS(SELECT 1 FROM posts WHERE user_id = users.id)')
    

    由于这是一个在任何地方都可以使用的相当复杂的查询,您可以将其放在User 的命名范围内:

    class User < ActiveRecord::Base
      scope :without_posts, -> { where('NOT EXISTS(SELECT 1 FROM posts WHERE user_id = users.id)') }
    end
    

    现在您可以在应用程序的其他地方使用此范围:

    User.without_posts
    

    【讨论】:

    • 注意:第一个不适用于 PostgreSQL(不返回任何结果),但带有子查询的 NOT EXISTS 可以很好地工作。
    • 更多 Rails 风格的方式可能是User.includes(:posts).where(posts: {id: nil}).references(:posts)。这应该解决任何数据库特定问题,哈希将在数据库适配器级别处理(我相信)。
    【解决方案2】:

    我会尝试类似的东西

    User.joins(posts).where("count(posts.id) = 0")
    

    返回所有有 0 个帖子的用户。

    【讨论】:

    • 这似乎在 Postgres 中不起作用:PG::GroupingError: ERROR: aggregate functions are not allowed in WHERE
    【解决方案3】:

    使用 rails 6.1,更简单:

    User.where.missing(:posts)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 2011-09-21
      相关资源
      最近更新 更多