1. ホーム
  2. django

[解決済み] DjangoでSELECT COUNT(*) GROUP BYとORDER BYを行うにはどうすればよいですか?

2022-06-18 07:27:56

質問

トランザクションモデルを使用して、システムで発生するすべてのイベントを記録しています。

class Transaction(models.Model):
    actor = models.ForeignKey(User, related_name="actor")
    acted = models.ForeignKey(User, related_name="acted", null=True, blank=True)
    action_id = models.IntegerField() 
    ......

上位5人の俳優を自分のシステムに取り込むにはどうすればよいですか?

SQLでは、基本的に次のようになります。

SELECT actor, COUNT(*) as total 
FROM Transaction 
GROUP BY actor 
ORDER BY total DESC

どのように解決するのですか?

ドキュメントによると、使用する必要があります。

from django.db.models import Count
Transaction.objects.all().values('actor').annotate(total=Count('actor')).order_by('total')

values() : "group by "に使用する列を指定します。

Django のドキュメントです。

values() 節が結果セットで返される列を制限するために使用されている場合、アノテーションの評価方法は以下のようになります。 を使用する場合、アノテーションを評価する方法は若干異なります。 は少し異なります。元の QuerySet の各結果に対してアノテーションされた結果を返すのではなく、元の QuerySet の結果に対してアノテーションされた結果を返します。 元のQuerySetの各結果に対してアノテーションされた結果を返すのではなく、元の結果は、フィールドのユニークな組み合わせに従ってグループ化されます。 で指定されたフィールドのユニークな組み合わせに従ってグループ化されます。 values() 節で指定されたフィールドのユニークな組み合わせに従ってグループ化されます。

annotate() : グループ化された値に対する操作を指定します。

Django のドキュメントです。

サマリー値を生成する 2 つ目の方法は、QuerySet 内の各オブジェクトに対して独立したサマリーを生成することです。例えば、もし を取得する場合、各書籍に貢献した著者の人数を知りたいと思うかもしれません。 を知りたい場合があります。各書籍は、著者と多対多のリレーションシップを持っています。 との多対多のリレーションシップがあります。 についてこの関係を要約したいと思います。

オブジェクトごとのサマリーは、annotate()節を使用して生成することができます。 annotate() 節が指定されると、QuerySet 内の各オブジェクトに指定された注釈が付きます。 の各オブジェクトは、指定された値で注釈されます。

order by節は自明です。

要約すると、著者のクエリセットを生成し、アノテーションを追加し(これは返された値に追加のフィールドを追加します)、最後に、この値でそれらを並べ替えます。

参照先 https://docs.djangoproject.com/en/dev/topics/db/aggregation/ を参照してください。

注意すべき点: Count を使用する場合、Count に渡された値は集約に影響せず、最終的な値に付けられる名前に影響するだけです。集計器は、Count に渡された値ではなく、(上記のように)値のユニークな組み合わせによってグループ化します。次のクエリも同じです。

Transaction.objects.all().values('actor').annotate(total=Count('actor')).order_by('total')
Transaction.objects.all().values('actor').annotate(total=Count('id')).order_by('total')