Rails has_many关联计数子行

什么是有效抓取父表的所有行的“轨道方式”以及每行的子节点数?

我不想使用counter_cache因为我想根据某些时间条件运行这些计数。

陈词滥调的博客示例:文章表。 每篇文章都有0条或更多条评论。

我希望能够在过去的一小时,一天,一周内提取每篇文章的评论数量。

但是,理想情况下,我不想迭代列表并为每篇文章单独执行sql调用,也不想使用:include来预取所有数据并在应用服务器上处理它。

我想运行一个SQL语句并获得一个包含所有信息的结果集。

我知道我可以硬编码完整的SQL,也许可以使用.find并只设置:joins:group:conditions参数……但我想知道是否有“更好”的方式…又名“铁路方式”

提前致谢

这个activerecord调用应该做你想要的:

 Article.find(:all, :select => 'articles.*, count(posts.id) as post_count', :joins => 'left outer join posts on posts.article_id = articles.id', :group => 'articles.id' ) 

这将返回一个文章对象列表,每个文章对象都有方法post_count ,其中包含文章中作为字符串的post数。

该方法执行类似于以下的sql:

 SELECT articles.*, count(posts.id) AS post_count FROM `articles` LEFT OUTER JOIN posts ON posts.article_id = articles.id GROUP BY articles.id 

如果您很好奇,这是您在运行此类查询时可能会看到的MySQL结果的示例:

 +----+----------------+------------+ | id | text | post_count | +----+----------------+------------+ | 1 | TEXT TEXT TEXT | 1 | | 2 | TEXT TEXT TEXT | 3 | | 3 | TEXT TEXT TEXT | 0 | +----+----------------+------------+ 

Rails 3版本

对于Rails 3,你会看到这样的东西:

 Article.select( "articles.*, count(comments.id) AS comments_count" ) .joins( "LEFT OUTER JOIN comments ON comments.article_id = articles.id" ) .group( "articles.id" ) 

感谢Gdeglin为Rails 2版本。

我用来解决这个问题的一个简单方法是

在我的模型中,我做了:

 class Article < ActiveRecord::Base has_many :posts def count_posts Post.where(:article_id => self.id).count end end 

现在,您可以使用例如:

 Articles.first.count_posts 

我不确定它是否可以更有效,但它的解决方案,在我看来比其他更优雅。

从SQL的角度来看,这看起来微不足道 – 只需编写一个新查询。

从Rails的角度来看,您提到的值是计算值。 因此,如果使用find_by_sql ,Model类将不知道计算字段,因此即使您设法将查询转换为Rails,也会将计算值作为字符串返回。 请参阅以下链接问题。
一般的漂移(从我得到的问题的答案)是有一个单独的类负责汇总/计算所需的值。

如何让rails以正确的数据类型而不是字符串返回SUM(columnName)属性?