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}]>