28

Djangoには、クエリセット用の優れた新しいannotate()関数があります。ただし、単一のクエリセット内の複数のアノテーションに対して正しく機能させることはできません。

例えば、

tour_list = Tour.objects.all().annotate( Count('tourcomment') ).annotate( Count('history') )

ツアーには、複数のツアーコメントと履歴エントリを含めることができます。このツアーに存在するコメントと履歴エントリの数を取得しようとしています。結果として

history__count and tourcomment__count

値は正しくありません。annotate()呼び出しが1つしかない場合、値は正しくなります。

LEFT OUTER JOIN2つのsから来るある種の乗法効果があるようです。たとえば、ツアーに3つの履歴と3つのコメントがある場合、9が両方のカウント値になります。12の履歴+1つのコメント=両方の値で12。1履歴+0コメント=1履歴、0コメント(これはたまたま正しい値を返します)。

結果のSQL呼び出しは次のとおりです。

SELECT `testapp_tour`.`id`, `testapp_tour`.`operator_id`, `testapp_tour`.`name`, `testapp_tour`.`region_id`, `testapp_tour`.`description`, `testapp_tour`.`net_price`, `testapp_tour`.`sales_price`, `testapp_tour`.`enabled`, `testapp_tour`.`num_views`, `testapp_tour`.`create_date`, `testapp_tour`.`modify_date`, `testapp_tour`.`image1`, `testapp_tour`.`image2`, `testapp_tour`.`image3`, `testapp_tour`.`image4`, `testapp_tour`.`notes`, `testapp_tour`.`pickup_time`, `testapp_tour`.`dropoff_time`, COUNT(`testapp_tourcomment`.`id`) AS `tourcomment__count`, COUNT(`testapp_history`.`id`) AS `history__count` 
FROM `testapp_tour` LEFT OUTER JOIN `testapp_tourcomment` ON (`testapp_tour`.`id` = `testapp_tourcomment`.`tour_id`) LEFT OUTER JOIN `testapp_history` ON (`testapp_tour`.`id` = `testapp_history`.`tour_id`)
GROUP BY `testapp_tour`.`id`
ORDER BY `testapp_tour`.`name` ASC

annotate()への単一の呼び出しを含む2つのクエリセットの結果を組み合わせてみましたが、正しく機能しません...順序が同じになることを実際に保証することはできません。そしてそれは過度に複雑で厄介なように見えるので、私はもっと良いものを探していました...

tour_list = Tour.objects.all().filter(operator__user__exact = request.user ).filter(enabled__exact = True).annotate( Count('tourcomment') )
tour_list_historycount = Tour.objects.all().filter( enabled__exact = True ).annotate( Count('history') )
for i,o in enumerate(tour_list):
    o.history__count = tour_list_historycount[i].history__count

助けてくれてありがとう。Stackoverflowは、過去に多くの回答済みの質問で私のお尻を救ってきましたが、私はまだこれに対する答えを見つけることができませんでした。

4

3 に答える 3

59

ご意見をありがとうございます。それはうまくいきませんでしたが、正しい方向に私を導きました。両方の Count() 呼び出しに個別を追加することで、最終的にこれを解決できました。

Count('tourcomment', distinct=True)
于 2009-08-12T15:06:28.160 に答える
0

これで問題が解決するとは限りませんが.order_by()、呼び出しに追加してみてください。あれは:

tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history')).order_by()

この理由は、django が ORDER BY 句のすべてのフィールドを選択する必要があるためです。それ以外の場合は同一の結果が選択されます。を追加.order_by()すると、ORDER BY 句が完全に削除され、これが発生しなくなります。この問題の詳細については、集計のドキュメントを参照してください。

于 2009-08-12T09:44:04.667 に答える