Django:ORM聚合分组查询aggregate、annotate

聚合查询

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。

from django.db.models import Max,Avg,F,Q
models.Book.objects.all().aggregate(Avg("price"))
{'price__avg': 192.593333}

 

如果你想要为聚合值指定一个名称,可以向聚合子句提供它。  

models.Book.objects.all().aggregate(avg_price=Avg("price"))
{'avg_price': 192.593333}

 

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

from django.db.models import Max,Avg,F,Q,Min,Count,Sum
models.Book.objects.all().aggregate(Avg("price"),Max("price"),Min("price"),Sum("price"))
{'price__avg': 192.593333, 'price__max': Decimal('233.33'), 'price__min': Decimal('111.12'), 'price__sum': Decimal('577.78')}

 

分组查询

为调用的QuerySet中每一个对象都生成一个独立的统计值 
统计每一本书的作者个数

models.Book.objects.all().annotate(authorNum=Count("author"))
<QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三>]>
book_list = models.Book.objects.all().annotate(authorNum=Count("author"))
for i in book_list:
    print(i.authorNum)
2
2
1
 

统计出每个出版社买的最便宜的书的价格 
方法一

pulisher_list = models.Publisher.objects.all().annotate(min_price=Min("book__price"))
for i in pulisher_list:
    print(i.min_price)
111.12
12.00
456.00
785.00

 

方法二

tmp = models.Book.objects.all().values("author__name").annotate(min_price=Min("price"))
for i in tmp:
    print(i.min_price)
Traceback (most recent call last):
  File "<input>", line 2, in <module>
AttributeError: 'dict' object has no attribute 'min_price'
for i in tmp:
    print(i)

{'author__name': '小一', 'min_price': Decimal('111.12')}
{'author__name': '小二', 'min_price': Decimal('233.33')}
{'author__name': '小三', 'min_price': Decimal('111.12')}
{'author__name': None, 'min_price': Decimal('12.00')}

 

统计不止一个作者的图书

tmp = models.Book.objects.all().annotate(au=Count("author")).filter(au__gt=1)
tmp
<QuerySet [<Book: 书一>, <Book: 书二>]>

 

根据一本图书作者数量的多少对查询集 QuerySet进行排序

tmp = models.Book.objects.all().annotate(au=Count("author")).order_by("au")
tmp
<QuerySet [<Book: 书四>, <Book: 书五>, <Book: 书六>, <Book: 书三>, <Book: 书一>, <Book: 书二>]>

 

查询各个作者出的书的总价格

tmp = models.Author.objects.all().annotate(total=Sum("books__price")).values("name","total")
tmp
<QuerySet [{'name': '小一', 'total': Decimal('344.45')}, {'name': '小二', 'total': Decimal('689.33')}, {'name': '小三', 'total': Decimal('111.12')}, {'name': '小四', 'total': None}]>

 

posted @ 2019-01-19 14:25  追赶菜鸟  阅读(284)  评论(0编辑  收藏  举报