Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord: count with groups

I have a model of a post with has_many comments. Every post has a thread id (but there is no model named Thread).

So if I want to count the number of threads in this post I do smth like

> post.comments.count(:thread, :distinct => true)
SELECT COUNT(DISTINCT "comments"."thread") FROM "comments" WHERE "comments"."post_id" = 3

And this works fine. But what if I want to count the number of threads with only one comment?

> post.comments.group(:thread).having('COUNT(*) == 1').count
SELECT COUNT(*) AS count_all, thread AS thread FROM "comments" WHERE "comments"."post_id" = 3 GROUP BY thread HAVING COUNT(*) == 1 ORDER BY id

So I have a OrderedHash instead of Integer. And I have to do the unnecessary step

> post.comments.group(:thread).having('COUNT(*) == 1').count.count

Is there any better solution?

like image 849
Ximik Avatar asked Feb 29 '12 11:02

Ximik


1 Answers

This is expected behavior.

post.comments.group(:thread).having('COUNT(*) == 1').count

This is returning a hash where the key is the thread id and the value is the count. I believe this is the case anytime you do a group with an aggregate function in rails. You must do the second count to get the number of results that the first query matches.

I am not sure how this would look in Rails, but here is the SQL that I think you want:

SELECT COUNT(*) FROM 
  SELECT COUNT(*) AS count_all, thread AS thread 
  FROM "comments"
  WHERE "comments"."post_id" = 3 
  GROUP BY thread
  HAVING COUNT(*) == 1
  ORDER BY id
like image 91
Brad Avatar answered Sep 28 '22 09:09

Brad