如何在 Django ORM 中执行 GROUP BY ... COUNT 或 SUM?

How to execute a GROUP BY ... COUNT or SUM in Django ORM?

序言:

这是SO中经常出现的问题:

我已经在 SO 文档中编写了一个示例,但由于该文档将于 2017 年 8 月 8 日关闭,我将遵循 this widely upvoted and discussed meta answer 的建议并将我的示例转换为自我回答 post.

当然,我也很乐意看到任何不同的方法!!


问题:

假设模型:

class Books(models.Model):
    title  = models.CharField()
    author = models.CharField()
    price = models.FloatField()

如何使用 Django ORM 对该模型执行以下查询:

我们可以在 Django ORM 上执行 GROUP BY ... COUNTGROUP BY ... SUM SQL 等效查询,使用 annotate(), values(), the django.db.models's Count and Sum methods respectfully and optionally the order_by() 方法:

  • 分组依据...计数:

     from django.db.models import Count
    
     result = Books.objects.values('author')
                           .order_by('author')
                           .annotate(count=Count('author'))
    

    现在结果包含一个 字典 和两个键:authorcount:

       author    | count
     ------------|-------
      OneAuthor  |   5
     OtherAuthor |   2
        ...      |  ...
    
  • 分组依据...总和:

     from django.db.models import Sum
    
      result = Books.objects.values('author')
                            .order_by('author')
                            .annotate(total_price=Sum('price'))
    

    现在结果包含一个 字典 ,其中有两列:authortotal_price:

       author    | total_price
     ------------|-------------
      OneAuthor  |    100.35
     OtherAuthor |     50.00
         ...     |      ...
    

2021 年 4 月 13 日更新

正如@dgw 在评论中指出的那样,在模型使用元选项对行进行排序的情况下(例如 ordering), the order_by() 子句 是最重要的 聚合成功!

在 SUM() 分组中,你几乎可以得到两个字典对象,比如

inv_data_tot_paid =Invoice.objects.aggregate(total=Sum('amount', filter=Q(status = True,month = m,created_at__year=y)),paid=Sum('amount', filter=Q(status = True,month = m,created_at__year=y,paid=1)))
print(inv_data_tot_paid)
##output -{'total': 103456, 'paid': None}

不要尝试超过两个查询过滤器否则,你会得到类似

的错误