使用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")
}
我假设零帖的作者根本没有被第三行选中......所以解决方案是什么?
答案 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索引,这将最有效。