2012-02-29 5 views
6

У меня есть модель публикации с комментариями has_many. У каждого сообщения есть идентификатор потока (но нет модели с именем Thread).ActiveRecord: count with groups

Так что, если я хочу, чтобы подсчитать количество нитей в этом посте я как-л

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

И это работает отлично. Но что, если я хочу подсчитать количество потоков только с одним комментарием?

> 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 

Поэтому у меня есть OrderedHash вместо Integer. И я должен сделать ненужный шаг

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

Есть ли лучшее решение?

ответ

12

Ожидаемое поведение.

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

Это возвращает хеш, где ключ - это идентификатор потока, а значение - это счетчик. Я считаю, что это так, когда вы делаете группу с совокупной функцией в рельсах. Вы должны сделать второй счет, чтобы получить количество результатов, совпадающих с первым запросом.

Я не знаю, как это будет выглядеть в Rails, но вот SQL, что я думаю, что вы хотите:

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 
+0

Вообще SQL ожидает «=» не «==» эквивалентности. Возможно, ваш ответ правильный для некоторых брендов SQL, но он не работает в MySQL без этого изменения. –

+0

Это правильно. Однако я старался соответствовать формату, который он использовал в исходном сообщении. – Brad