汇总计数(“评论”.id)+计数(“评论”.id)为my_count时的奇怪结果

时间:2013-09-05 10:50:21

标签: ruby-on-rails ruby ruby-on-rails-3

在下面的查询中,我会计算出版物的评论和评论数量。我总结了这样的评论和评论: .select('“publications”。*,count(“reviews”.id)+ count(“comments”.id)my_count')

假设出版物有3条评论,总共3条评论为6条,但my_count总是显示更大的数字。幕后发生了什么以及如何使它正常计数?

Publication.joins(:reviews, :comments)
                                  .select('"publications".*, count("reviews".id) + count("comments".id) as my_count')
                                  .group('"publications".id')
                                  .order("my_count DESC")

2 个答案:

答案 0 :(得分:1)

生成的SQL可能如下所示:

SELECT publications.id, COUNT(reviews.id) + COUNT(comments.id) AS my_count
FROM publications p
INNER JOIN reviews r ON p.id = r.publication_id
INNER JOIN comments c ON p.id = c.publication_id
GROUP BY p.id
ORDER BY my_count DESC

让我们暂时摆脱分组,看看以下输入发生了什么:

publications: [{ id: 1 }],
reviews: [{ publication_id: 1, id: 1 }, { publication_id: 1, id: 2 },{ publication_id: 1, id: 3 }]
comments: [{ publication_id: 1, id: 10 }, { publication_id: 1, id: 20 }]

所以有3条评论和2条评论。但是,此查询将返回6行:

SELECT *
FROM publications p
INNER JOIN reviews r ON p.id = review.publication_id
INNER JOIN comments c ON p.id = comment.publication_id

publication.id | review.id | comment.id
1              | 1         | 10
1              | 2         | 10
1              | 3         | 10
1              | 1         | 20
1              | 2         | 20
1              | 3         | 20

而且,当你对它进行分组时,它将返回6 + 6 = 12作为总计数。 一种可能的解决方法是COUNT(DISTINCT reviews.id) + COUNT(DISTINCT comments.id)。可能,这不是性能方面的最佳解决方案。

答案 1 :(得分:0)

正如DNNX指出的那样,这是因为你已经陷入所谓的“断层陷阱” - 由于多个一对多连接,行数被夸大了。

您可以尝试将其作为短期替代方案:

Publication.select('"publications".*,
                     coalesce((select count(*) from reviews r where r.publication_id = pubications.id),0)
                     + coalesce((select count(*) from comments c where c.publication_id = pubications.id),0) as my_count')
            .order("my_count DESC")

但是,我建议您在发布评论和评论时放置反缓存。