Django聚合函数

提到聚合函数,首先我们要知道的就是这些聚合函数是不能在django中单独使用的,要想在django中使用这些聚合函数,就必须把这些聚合函数放到支持他们的方法内去执行。支持聚合函数的方法有两种,分别是aggregate和annotate,这两种方法执行的原生SQL以及结果都有很大的区别。

aggregate方法是一个QuerySet对象的API,在执行聚合函数的时候,是对QuerySet整个对象的某个属性汇总,在汇总时不会使用该模型的主键进行group by进行分组,得到的是一个结果字典。同时,该方法支持聚合关联表(如使用ForeignKey)中的字段,在聚合连表中字段时,传递该字段的方式与查询连表时传递字段的方式相同,会使用到”__”。

而annotate方法不但可以执行聚合函数,也可以传递F、Q对象为当前QuerySet生成一个新的属性。annotate方法一般聚合的是连表中的字段,会为当前QuerySet中的每个对象生成一个独立的摘要,为查询的模型增加一个新的属性,这个属性的值就是使用聚合函数所得到的值,在使用这个聚合函数的时候annotate会使用这个模型的主键进行group by进行分组(注意这里只有在使用聚合函数生成新字段的时候会进行group by,在使用F、Q表达式增添新字段时,并不会使用group by,然后在连表中根据分组的结果进行聚合,这一点正符合为QuerySet中每个对象增加一个独立摘要的事实。

那么他们两者的区别到底在哪儿呢?

相同:这2个方法都可以执行聚合函数。

不同: aggregate返回的是一个字段,在这个字典中存储的是这个聚合函数执行的结果。而annotate返回的是一个 QuerySet 对象,并且会在查找的模型上添加一个聚合函数属性。aggregate不会做分组,而annotate会使用group by子句进行分组,只有调用了group by子句,才能对每一条数据求聚合函数的值。

聚合函数

在Django中,聚合函数都是在django.db.models模块下的,具体的聚合函数有Avg、Count、Max、Min、Sum,现在我们一一介绍这些函数的作用:

AVG

Avg一般用来计算平均值,使用于与数值相关的字段,如果使用aggregate方法来执行这个函数,那么会得到一个字典,默认情况下,字典的键为field__avg,值为执行这个聚合函数所得到的值,示例代码如下:

from django.db.models import Avg
res = qkb.objects.aggregate(Avg('tcbl'))
print(res)

# 返回的内容如下
{'tcbl__avg': 2.4829386866278282}

# 这里如果想查看具体执行的SQL语句、我们可以通过print(res.queries)来实现。因为print(res.query)只能在QuerySet对象上使用、而不能在字典上使用;这里print(res)返回的就是一个字典。
[{'sql': 'QUERY = \'SELECT AVG("QKB"."TCBL") AS "TCBL__AVG" FROM "QKB"\' - PARAMS = ()', 'time': '3.180'}]

# 不使用默认聚合函数名
res = qkb.objects.aggregate(tcbl_avg=Avg('tcbl'))

注:这里强调一下,聚合函数执行完成后,给聚合函数的值取名;取名的规则默认是’field+__+聚合函数名字’的形式。比如上面代码形成的名字就叫做‘tcbl_avg’。如果不想使用默认的名字,我们可以在使用聚合函数的时候传递关键字参数进去,参数的名字就是聚合函数执行完成以后的名字,示例代码如上。

Count

计算数量,基本用法与Avg相同,在使用这个聚合函数的时候可以传递一个distinct参数用来去重:

from django.db.models import Count
res = qkb.objects.aggregate(Count('tcbl',distinct=True))

Max/Min

计算某个字段的最大值和最小值,用法与Avg一样

from django.db.models import Max
res = qkb.objects.aggregate(Max('tcbl'))

from django.db.models import Min
res = qkb.objects.aggregate(Min('tcbl'))

Sum

计算总和,用法与Avg一样

from django.db.models import Sum
res = qkb.objects.aggregate(Sum('tcbl'))

推荐文章