9

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?

1 Answer 1

19

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
Sign up to request clarification or add additional context in comments.

2 Comments

Generally SQL expects "=" not "==" for equivalence. Your answer is probably correct for some brands of SQL but it does fail on MySQL without this change.
That is correct. However I was trying to be consistent with the format he was using in the original post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.