How to do SELECT COUNT(*) GROUP BY and ORDER BY in Django?

后端 未结 2 1159
礼貌的吻别
礼貌的吻别 2020-12-04 09:49

I\'m using a transaction model to keep track all the events going through the system

class Transaction(models.Model):
    actor = models.ForeignKey(User, rel         


        
2条回答
  •  醉酒成梦
    2020-12-04 10:06

    According to the documentation, you should use:

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

    values() : specifies which columns are going to be used to "group by"

    Django docs:

    "When a values() clause is used to constrain the columns that are returned in the result set, the method for evaluating annotations is slightly different. Instead of returning an annotated result for each result in the original QuerySet, the original results are grouped according to the unique combinations of the fields specified in the values() clause"

    annotate() : specifies an operation over the grouped values

    Django docs:

    The second way to generate summary values is to generate an independent summary for each object in a QuerySet. For example, if you are retrieving a list of books, you may want to know how many authors contributed to each book. Each Book has a many-to-many relationship with the Author; we want to summarize this relationship for each book in the QuerySet.

    Per-object summaries can be generated using the annotate() clause. When an annotate() clause is specified, each object in the QuerySet will be annotated with the specified values.

    The order by clause is self explanatory.

    To summarize: you group by, generating a queryset of authors, add the annotation (this will add an extra field to the returned values) and finally, you order them by this value

    Refer to https://docs.djangoproject.com/en/dev/topics/db/aggregation/ for more insight

    Good to note: if using Count, the value passed to Count does not affect the aggregation, just the name given to the final value. The aggregator groups by unique combinations of the values (as mentioned above), not by the value passed to Count. The following queries are the same:

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

提交回复
热议问题