聚合查询是指对一个数据表(Model)中某个字段的数据进行部分或者全部统计查询的一种方式,比如所有全部书的平均价格或者是书籍的总数量等等,在这些时候就会使用到聚合查询这种方法。而分组查询同样也属于聚合查询中的一种,只是更加复杂一点而已,在学习本节的知识时候,如果你有较好的MySQL知识储备,那么学习本节知识将会变得再简单不过了。下面就让我们开始学习吧。
1.聚合查询的应用1)不带分组的聚合查询对数据表计算统计值,需要使用aggregate方法,提供的参数可以是一个或者多个聚合函数,aggregate是QuerySet的一个子句,它的返回值是一个字典类型,键是聚合的关键字,值是聚合后的统计结果。不带分组的聚合查询是指对将全部数据进行集中统计查询,Django定义了一些常用的聚合函数,比如求平均值(Avg)、计数(Count)、求最值(Max和Min)以Sum求和。它们统一定义在django.db.models模块中,所以再使用聚合函数时,同样需要提前导入,为了方便使用,我们采用下面的方式引入:
fromdjango.db.modelsimport*
它的语法格式如下所示,它的返回值是一个字典,以统计结果变量名为key,以统计值为value:
MyModel.objects.aggregate(统计结果变量名=聚合函数(列名))
我们通过求所有书籍的价格平均值与所书籍数量来进行实例演练:
#求所有书籍的平均价格fromindex.modelsimportBookfromdjango.db.modelsimport*result=Book.objects.aggregate(myAvg=Avg(price))print("平均价格是:",result[myAvg])print("result=",result)#result={myAvg:Decimal(47.)}#求一共有多少本书result=Book.objects.aggregate(MyCulate=Count(title))print("数据记录总个数是:",result[MyCulate])print("result=",result)#result={MyCulate:5}#传递多个聚合函数一起求值result=Book.objects.aggregate(l=Min("price"),m=Max("price"),n=Avg("retail_price"))print("result=",result)#result={l:Decimal(25.00),m:Decimal(65.00),n:Decimal(.)}
2.聚合分组查询应用
分组聚合是指通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。简单的理解就是对QuerySet中的每一个Model对象都生成一个统计值。分组聚合使用annotate方法完成。它的语法格式和聚合查询一样如下所示:
QuerySet.annotate(结果变量名=聚合函数(列名))
分组聚合的实现主要两个步骤:首先使用MyModel.objects.values获得要分组聚合的列,它的返回结果是一个QuerySet类型的字典,然后通过QuerySet.annotate(变量名=聚合函数(列名))的方法分组聚合得到相应的结果。下面我们通过实例进行说明,通过分组聚合查询获取价格相同的书籍数量:
#在index/views.py添加代码fromdjango.db.modelsimportCountfromindex.modelsimportBook,PubNamedeftest_annotate(request):#得到所有出版社的查询集合QuerySetbk_set=Book.objects.values(price)#bk=Book.objects.get(id=1)#print(书名:,bk.title,出版社是:,bk.pub.pubname)#根据出版社QuerySet查询分组,出版社和Count的分组聚合查询集合bk_count_set=bk_set.annotate(myCount=Count(price))#返回查询集合foriteminbk_count_set:#通过外键关联进行查询bk_set.pub.pubnameprint("价格是:",item[price],"同等价格书籍数量:",item[myCount])returnHttpResponse(请在CMD命令行控制台查看结果)#路由配置为忘记:path(annotate/,views.test_annotate)
最终在CMD命令行会得到如下输出:
价格是:59.00同等价格书籍数量:1价格是:25.00同等价格书籍数量:1价格是:45.00同等价格书籍数量:2价格是:65.00同等价格书籍数量:1
由于annotate的返回值是一个QuerySet对象,所以我可以通过query属性查看其执行的SQL语句,如下所示:
SELECT`index_book`.`price`,COUNT(`index_book`.`price`)AS`myCount`FROM`index_book`GROUPBY`index_book`.`price`ORDERBYNULL
从SQL语句可以得出,annotate按照price分组,并且在SELECT中对price进行了计数。默认情况下,annotate会对每一个Model对象计算统计值。但是,如果使用了values方法中指定的字段,Django会先按照该字段对Model对象进行分组,再去对每个分组计算统计值。
3.总结归纳本节主要讲解了聚合查询以及分组聚合查询的使用方法,还给大家介绍了几个常用的聚合函数。聚合查询和分组查询分别调用不同的方法来实现,聚合查询是aggregate,而分组聚合查询是annotate。后者经常配合values方法来选取要分组的字段。在这里大家还要注意,annotate和values方法的顺序非常重要,会影响实际的查询效果。上面实例就是values在前的情况,如果annotate在前会产生不同的影响,如下所示:
In[41]:Book.objects.annotate(t=Max(price)).values(id,t)Out[41]:QuerySet[{id:1,t:Decimal(59.00)},{id:2,t:Decimal(25.00)},{id:3,t:Decimal(45.00)},{id:4,t:Decimal(65.00)},{id:5,t:Decimal(45.00)}]#按照values提供的参数分别作为键和值。
至此我们将Django提供的各种查询方式讲解完毕,我们用了7节的内容对此知识点做了详细介绍。熟练掌握这些章节的内容,对我们从数据库获取数据的操作会有很大帮助,也能够满足一些实际业务上需求。
预览时标签不可点收录于话题#个上一篇下一篇最近更新
推荐文章