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 が返されます。考えられる回避策の 1 つは、実行することですCOUNT(DISTINCT reviews.id) + COUNT(DISTINCT comments.id)。おそらく、これはパフォーマンスの点で最適なソリューションではありません。

于 2013-09-05T11:10:38.590 に答える
0

DNNX が指摘しているように、これは「キャズム トラップ」と呼ばれるものに陥ったために発生します。複数の 1 対多の結合により、行数が増加します。

短期的な代替手段としてこれを試すことができます:

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")

ただし、レビューやコメント用にパブリケーションにカウンター キャッシュを配置することをお勧めします。

于 2013-09-05T12:39:14.280 に答える