如何创建一个范围来查找“零帖子的作者”?

时间:2010-10-12 04:30:00

标签: ruby-on-rails ruby activerecord arel

使用Rails 3,这个范围可以正常工作:

      scope :with_posts, lambda {
        joins(:posts).
        select("authors.*, count(posts.id) posts_count").
        group("posts.author_id").
        having("posts_count > 0")
      }

生成的SQL是:

SELECT authors.*, count(posts.id) posts_count FROM `authors` INNER JOIN `posts` ON `posts`.`author_id` = `author`.`id` GROUP BY posts.author_id HAVING posts_count > 0

但它的反向返回没有结果:

      scope :with_posts, lambda {
        joins(:posts).
        select("authors.*, count(posts.id) posts_count").
        group("posts.author_id").
        having("posts_count < 1")
      }

我假设零帖的作者根本没有被第三行选中......所以解决方案是什么?

4 个答案:

答案 0 :(得分:1)

由于正在创建内部联接SQL,因此它将显示两个表中可用记录的结果。因此,尝试创建外连接并在下一个表中查找/计算空值

尝试外部加入

答案 1 :(得分:1)

你是对的,连接是排除所有零帖子的作者,你需要的是一个外连接。

我不知道rails 3的语法,但在rails 2中,您可以使用SQL片段指定joins语句,而不是简单地使用关系名称。
User.all(:joins => 'outer join posts on users.id = posts.user_id')
Rails 3必须有一个等效的符号,但我从来没有使用它,所以我不知道确切的语法。这应该是一般的想法。

答案 2 :(得分:0)

我对此并不了解,但我建议你看看这个Railscast

希望这适合你。

答案 3 :(得分:0)

scope :without_posts, lambda {
    where("id NOT IN (?)", Posts.select("author_id").group("author_id") )
}

如果您的数据库中有author_id索引,这将最有效。