在下面的查询中,我会计算出版物的评论和评论数量。我总结了这样的评论和评论: .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")
答案 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")
但是,我建议您在发布评论和评论时放置反缓存。