0

在下面的查询中,我计算了有多少评论和评论出版物。我总结了这样的评论和评论:.select('"publications".*, count("reviews".id) + count("comments".id) as 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")
4

2 回答 2

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). 就性能而言,这可能不是最佳解决方案。

于 2013-09-05T11:10:38.590 回答
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")

但是,我建议您在 Publication 上放置计数器缓存以进行评论和评论。

于 2013-09-05T12:39:14.280 回答