【Python】【进阶篇】40、Django聚合查询和分组查询

news/2025/2/19 10:25:13

目录

  • 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(统计结果变量名=聚合函数('列名'))

我们通过求所有书籍的价格平均值与所书籍数量来进行实例演练:

python">#求所有书籍的平均价格
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(变量名=聚合函数(‘列名’))的方法分组聚合得到相应的结果。下面我们通过实例进行说明,通过分组聚合查询获取价格相同的书籍数量:

python">#在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 在前会产生不同的影响,如下所示:

python">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 节的内容对此知识点做了详细介绍。熟练掌握这些章节的内容,对我们从数据库获取数据的操作会有很大帮助,也能够满足一些实际业务上需求。

文章来源:https://blog.csdn.net/NQBXHN/article/details/130648594
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.niftyadmin.cn/n/330202.html

相关文章

康耐视智能相机IS2000与三菱PLC走MC协议通讯设置详细步骤及案例详解

1.IS2000(SLMP扫描界面)设置如下: 控制器类型:PLC型号 IP地址:PLC地址 主机端口:16进制下的PLC通讯端口 2、IS2000设备寻址界面设置如下: 六大控制块存放区域根据PLC设定,偏移量及设备数可更改。3.打开GX WORKS软件,选择新建工程,点击“确定”,界面如下: 4.点击“连…

最常用的界线矢量数据大合集(文末有附下载方法)

最近收集了挺多比较常用的矢量界线数据&#xff0c;例如地理分区、气候分区等界线数据&#xff0c;在日常制图、学习、科研等方面使用频率比较高。废话不多说&#xff0c;这里给大家分享一下&#xff01;&#xff01; 1、中国农业熟制区划矢量数据 2、黄土高原空间范围矢量数据…

shell免交互

shell免交互 Here Document 免交互 使用I/O重定向的方式将命令列表提供给交互式程序或命令&#xff0c;比如 ftp、cat 或 read 命令。 是标准输入的一种替代品可以帮助脚本开发人员不必使用临时文件来构建输入信息&#xff0c;而是直接就地生产出一个“文件”并用作“命令”的…

POI 颜色IndexedColors枚举(EasyExcel 颜色)

枚举名枚举值颜色值BLACK10#000000WHITE11#FFFFFFRED12#FF0000BRIGHT_GREEN13#00FF00BLUE14#0000FFYELLOW15#FFFF00PINK16#FF00FFTURQUOISE17#00FFFFBLACK8#000000WHITE9#FFFFFFRED10#FF0000BRIGHT_GREEN11#00FF00BLUE12#0000FFYELLOW13#FFFF00PINK14#FF00FFTURQUOISE15#00FFFF…

【K8s】Helm

文章目录 一、Helm介绍1、背景2、介绍3、核心概念4、chart的基本结构5、helm官网 二、部署Helm1、安装helm客户端2、安装Tiller 三、常用指令1、仓库相关 helm repo2、chart相关 四、入门案例1、构建第一个chart2、将chart包发布到Repository3、在 Kubernetes 中部署应用4、升级…

【C++】图解类和对象(中)

类和对象&#xff08;中&#xff09; 文章目录 类和对象&#xff08;中&#xff09;一、类的6个默认成员函数二、构造函数1.定义2.特性3.对特性的理解及几点注意事项 二、析构函数总结 一、类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的…

C语言-程序环境与预处理

程序环境与预处理 程序环境翻译环境&#xff08;编译链接&#xff09;预编译编译汇编链接 执行环境 预处理预定义符#define定义的标识符 宏#define定义宏#define替换规则宏的命名约定带副作用的宏参数宏和函数的比较 其它#和##的使用字符串常量化运算符#标记粘贴运算符## 命令行…

使用fastify创建websocket连接,ws协议

安装 首先&#xff0c;确保你已经安装了 Fastify 和 WebSocket 相关的依赖包。如果尚未安装&#xff0c;可以使用以下命令安装&#xff1a; # 安装fastify npm i fastify # 安装websocket npm i fastify/websocket引入和注册 WebSocket 插件 在你的 JavaScript 文件中&#…