【Python】【进阶篇】40、Django聚合查询和分组查询 |
您所在的位置:网站首页 › django聚合查询 › 【Python】【进阶篇】40、Django聚合查询和分组查询 |
目录
40、Django聚合查询和分组查询1. 聚合查询的应用1) 不带分组的聚合查询
2. 聚合分组查询应用3. 总结归纳
40、Django聚合查询和分组查询
聚合查询是指对一个数据表(Model)中某个字段的数据进行部分或者全部统计查询的一种方式,比如所有全部书的平均价格或者是书籍的总数量等等,在这些时候就会使用到聚合查询这种方法。而分组查询同样也属于聚合查询中的一种,只是更加复杂一点而已,在学习本节的知识时候,如果你有较好的 MySQL 知识储备,那么学习本节知识将会变得再简单不过了。下面就让我们开始学习吧。 1. 聚合查询的应用 1) 不带分组的聚合查询对数据表计算统计值,需要使用 aggregate 方法,提供的参数可以是一个或者多个聚合函数,aggregate 是 QuerySet 的一个子句,它的返回值是一个字典类型,键是聚合的关键字,值是聚合后的统计结果。 不带分组的聚合查询是指对将全部数据进行集中统计查询,Django 定义了一些常用的聚合函数,比如求平均值(Avg)、计数(Count)、求最值(Max和Min)以 Sum 求和。它们统一定义在django.db.models模块中,所以再使用聚合函数时,同样需要提前导入,为了方便使用,我们采用下面的方式引入: from django.db.models import *它的语法格式如下所示,它的返回值是一个字典,以统计结果变量名为 key,以统计值为 value: MyModel.objects.aggregate(统计结果变量名=聚合函数('列名'))我们通过求所有书籍的价格平均值与所书籍数量来进行实例演练: #求所有书籍的平均价格 from index.models import Book from django.db.models import * result =Book.objects.aggregate(myAvg=Avg('price')) print("平均价格是:", result['myAvg']) print("result=", result) #result= {'myAvg': Decimal('47.800000')} #求一共有多少本书 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('127.800000')} 2. 聚合分组查询应用分组聚合是指通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。简单的理解就是对 QuerySet中的每一个 Model 对象都生成一个统计值。分组聚合使用 annotate 方法完成。它的语法格式和聚合查询一样如下所示: QuerySet.annotate(结果变量名=聚合函数('列名'))分组聚合的实现主要两个步骤:首先使用 MyModel.objects.values 获得要分组聚合的列,它的返回结果是一个 QuerySet 类型的字典,然后通过 QuerySet.annotate(变量名=聚合函数(‘列名’))的方法分组聚合得到相应的结果。下面我们通过实例进行说明,通过分组聚合查询获取价格相同的书籍数量: #在index/views.py 添加代码 from django.db.models import Count from index.models import Book,PubName def test_annotate(request): # 得到所有出版社的查询集合QuerySet bk_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')) # 返回查询集合 for item in bk_count_set: #通过外键关联进行查询bk_set.pub.pubname print("价格是:", item['price'], "同等价格书籍数量:", item['myCount']) return HttpResponse('请在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` GROUP BY `index_book`.`price` ORDER BY NULL从 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]: '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 节的内容对此知识点做了详细介绍。熟练掌握这些章节的内容,对我们从数据库获取数据的操作会有很大帮助,也能够满足一些实际业务上需求。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |