聚合查询与分组查询
聚合
aggregate(*args, **kwargs)
计算所有图书的平均价格
from django.db.models import Avg
Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}
如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
from django.db.models import Avg, Max, Min
Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
# 查询所有书籍的平均价格
from django.db.models import Avg,Count,Max,Min
ret=Book.objects.all().aggregate(Avg('price'))
# {'price__avg': 202.896}
# 可以改名字
ret=Book.objects.all().aggregate(avg_price=Avg('price'))
# 统计平均价格和最大价格
ret=Book.objects.all().aggregate(avg_price=Avg('price'),max_price=Max('price'))
# 统计最小价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), min_price=Min('price'))
# 统计个数和平均价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('price'))
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('nid'))
print(ret)
分组
annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。
总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。
查询练习
练习:统计每一本书作者个数
from django.db.models import Avg, Max, Sum, Min, Max, Count
book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
for book in book_list:
print(book.name)
print(book.author_num)
book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values('name','author_num')
print(book_list)
练习:统计每一个出版社的最便宜的书
publishList=Publish.objects.annotate(MinPrice=Min("book__price"))
for publish_obj in publishList:
print(publish_obj.name,publish_obj.MinPrice)
annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:
queryResult= Publish.objects.annotate(MinPrice=Min("book__price")).values_list("name","MinPrice")
print(queryResult)
练习:统计每一本以py开头的书籍的作者个数:
queryResult=Book.objects.filter(title__startswith="Py").annotate(num_authors=Count('authors'))
练习:统计不止一个作者的图书:(作者数量大于一)
ret=models.Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
print(ret)
练习:根据一本图书作者数量的多少对查询集 QuerySet进行排序:
Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
练习:查询各个作者出的书的总价格:
ret=models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")
print(ret)
练习:查询每个出版社的名称和书籍个数
ret=models.Publish.objects.all().annotate(c=Count('book__name')).values('name','c')
print(ret)