django的聚合函数和aggregate、annotate⽅法使⽤详解
⽀持聚合函数的⽅法:
勤能补拙意思提到聚合函数,⾸先我们要知道的就是这些聚合函数是不能在django中单独使⽤的,要想在django中使⽤这些聚合函数,就必须把这些聚合函数放到⽀持他们的⽅法内去执⾏。⽀持聚合函数的⽅法有两reword
种,分别是aggregate和annotate,这两种⽅法执⾏的原⽣SQL以及结果都有很⼤的区别,下⾯我们以实例操作的⽅式⼀⼀介绍:
# ⽰例模型:
class Author(models.Model):
"""作者模型"""
name = models.CharField(max_length=100)
age = models.IntegerField()
email = models.EmailField()
class Book(models.Model):
"""图书模型"""
name = models.CharField(max_length=100)
author = models.ForeignKey('Author',on_delete=models.CASCADE)
price = models.FloatField()
class BookOrder(models.Model):
"""图书订单模型"""
book = models.ForeignKey('Book',on_delete=models.CASCADE)
sailprice = models.FloatField()
create_time = models.DateTimeField(auto_now_add=True)
1、aggregate:这个⽅法时⼀个QuerySet对象的API,在执⾏聚合函数的时候,是对QuerySet整个对象的某个属性汇总,在汇总时不会使⽤该模型的主键进⾏group by进⾏分组,得到的是⼀个结果字
典。同时,该⽅法⽀持聚合关联表(如使⽤ForeignKey)中的字段,在聚合连表中字段时,传递该字段的⽅式与查询连表时传递字段的⽅式相同,会使⽤到"__"。⽰例代码如下:
from dels import Avg
from django.db import connection
1、对当前表中数据进⾏聚合:
result = Author.objects.aggregate(avg_age=Avg('age'))
print(connection.queries) # 打印执⾏时所有的查询语句
2、对连表中数据进⾏聚合:
result = Book.objects.aggregate(sum=Sum('bookorder__price'))
2、annotate:这个⽅法不但可以执⾏聚合函数,也可以传递F、Q对象为当前QuerySet⽣成⼀个新的属性。
这个⽅法⼀般聚合的是连表中的字段,会为当前QuerySet中的每个对象⽣成⼀个独⽴的摘要,为查询
的模型增加⼀个新的属性,这个属性的值就是使⽤聚合函数所得到的值,在使⽤这个聚合函数的时候
annotate会使⽤这个模型的主键进⾏group by进⾏分组(注意这⾥只有在使⽤聚合函数⽣成新字段的时候会进⾏group by,在使⽤F、Q表达式增添新字段时,并不会使⽤group by),然后在连表中根据可爱网名女生
分组的结果进⾏聚合,这⼀点正符合为QuerySet中每个对象增加⼀个独⽴摘要的事实。
使⽤这个⽅法执⾏聚合函数,得到的结果是⼀个QuerySet对象,结果依然能够调⽤filter()、order_by()甚⾄annotate()进⾏再次聚合,现在我想提取每⼀本书的平均销售的价格(注意销售价格在BookOrder
表中):
from dels import Avg
洁白的反义词 from django.db import connection
books = Book.objects.annotate(avg=Avg('bookorder__sailprice'))
for book in books:
print('%s/%s'%(book.name,book.avg)) # 注意这⾥的avg属性就是annotate执⾏聚合函数得到的
print(connection.queries)国庆节由来
聚合函数:
在Django中,聚合函数都是在dels模块下的,具体的聚合函数有Avg、Count、Max、Min、Sum,现在我们⼀⼀介绍这些函数的作⽤:
1、Avg:计算平均值,使⽤于与数值相关的字段,如果使⽤aggregate⽅法来执⾏这个函数,那么会得到⼀个字典,默认情况下,字典的键为field__avg,值为执⾏这个聚合函数所得到的值,⽰例代码如
下:
# 计算所有作者的平均年龄
result = Author.objects.aggregate(Avg('age'))
ppt中插入视频
print(result) # 结果为:{"age__avg": 23.8}
# 如果想要使⽤⾃定义的键,那么可以把aggregate中的未知参数变为关键字参数,该关键字就是得到的键,⽰例代码如下:
result = Author.objects.aggregate(avgAge=Avg('age'))
print(result) # 结果为:{"avgAge": 23.8}
# 如果使⽤annotate⽅法执⾏这个函数,那么得到的结果就是⼀个QuerySet对象,只不过这个对象中的每⼀个都会添加⼀个属性,这个属性的名称其实和上⾯的键⼀样,可以使⽤默认也可以⾃定义,使⽤⽅法与在aggregate中键名的定义⼀样,这⾥就不再赘述: books = Book.objects.annotate(avg=Avg('bookorder__sailprice'))
for book in books:
print('%s/%s'%(book.name,book.avg)) # 注意这⾥的avg属性就是annotate执⾏聚合函数得到的
print(connection.queries)
累赘的意思2、Count:计算数量,基本⽤法与Avg相同,在使⽤这个聚合函数的时候可以传递⼀个distinct参数⽤来去重:
# 计算总共有多少个订单
result = BookOrder.objects.aggregate(total=Count('id',distanct=True))
print(result) # 结果为:{"total": 18}
# 计算每本书的订单量
books = Book.objects.annotate(total=Count('bookorder__id'))
for book in books:
print('%s/%s'%(book.al))
3、Max和Min:计算某个字段的最⼤值和最⼩值,⽤法与Avg⼀样
4、Sum:计算总和,⽤法与Avg⼀样
注:总结⼀下,其实可以简单的理解使⽤aggregate时,是对QuerySet整个对象的某个属性汇总聚合,不会使⽤分组。⽽使⽤annotate⽅法时,是为QuerySet中的每个对象⽣成⼀个独⽴的摘要,⼀定会
使⽤分组,然后再聚合
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
家常腌蒜简单做法