计算Rails中的相关记录

时间:2012-06-18 06:04:40

标签: mysql ruby-on-rails activerecord

我正在尝试从数据库中的每个帖子中获取评论数量。但是,以下内容:

Post.includes(:comments).group("posts.id").count("comments.id")

引发mysql错误“Unknown column comments.id”,因为生成的sql似乎完全忽略了includes():

SELECT COUNT(comments.id) AS count_comments_id, posts.id AS posts_id
FROM `posts` GROUP BY posts.id

有趣的是,用join()替换includes()将产生有效的sql:

Post.joins(:comments).group("posts.id").count("comments.id")

SELECT COUNT(comments.id) AS count_comments_id, posts.id AS posts_id
FROM `posts` INNER JOIN `comments` ON `comments`.`post_id` = `posts`.`id`
GROUP BY posts.id

但上面的查询排除了所有包含0条评论的帖子,这不是我想要的。我需要的是生成以下SQL(但不写SQL,他是他)

SELECT COUNT(comments.id) AS count_comments_id, posts.id AS posts_id
FROM `posts` LEFT OUTER JOIN `comments` ON `comments`.`post_id` = `posts`.`id`
GROUP BY posts.id

4 个答案:

答案 0 :(得分:13)

includes方法在所有情况下都不会进行连接,而是出于性能原因批量获取关联(请参阅Rails :include vs. :joins)。

你需要做的是一个连接,你几乎在正确的路径上,但得到了组子句有点错误:

Post.select("posts.*, COUNT(comments.id) as comment_count").joins("LEFT OUTER JOIN comments ON (comments.post_id = posts.id)").group("posts.id")

请注意,此解决方案具有优势或实际返回Post对象(使用.count()在我的Rails 3.2上返回Hash),因此您可以遍历视图中的实际post对象并访问属性{{1} }。

答案 1 :(得分:3)

现在这个问题实际上更简单了:

Comment.joins(:post).group(:post_id).count(:post_id)

这会为您提供{<post_id> => <count of comments>}

的地图

答案 2 :(得分:1)

试试这个:

Post.select("COUNT(comments.id) AS count_comments_id, posts.id AS posts_id").
  includes(:comments).group("posts.id")

答案 3 :(得分:0)

如果您需要的只是帖子计数的哈希:{post_id1 => cnt1, post_id2 => cnt2, ...},那么强制关联的左连接将起作用:

  Post.joins("LEFT OUTER JOIN comments on posts.id=comments.post_id").
  group("posts.id").count("comments.id")