django的聚合函数和aggregate、annotate方法使用详解
作者:大蒙 发布时间:2023-06-27 16:07:46
支持聚合函数的方法:
提到聚合函数,首先我们要知道的就是这些聚合函数是不能在django中单独使用的,要想在django中使用这些聚合函数,就必须把这些聚合函数放到支持他们的方法内去执行。支持聚合函数的方法有两种,分别是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 django.db.models 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 django.db.models 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中,聚合函数都是在django.db.models模块下的,具体的聚合函数有Avg、Count、Max、Min、Sum,现在我们一一介绍这些函数的作用:
1、Avg:计算平均值,使用于与数值相关的字段,如果使用aggregate方法来执行这个函数,那么会得到一个字典,默认情况下,字典的键为field__avg,值为执行这个聚合函数所得到的值,示例代码如下:
# 计算所有作者的平均年龄
result = Author.objects.aggregate(Avg('age'))
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.name,book.total))
3、Max和Min:计算某个字段的最大值和最小值,用法与Avg一样
4、Sum:计算总和,用法与Avg一样
注:总结一下,其实可以简单的理解使用aggregate时,是对QuerySet整个对象的某个属性汇总聚合,不会使用分组。而使用annotate方法时,是为QuerySet中的每个对象生成一个独立的摘要,一定会使用分组,然后再聚合
来源:https://www.cnblogs.com/limaomao/p/9327740.html


猜你喜欢
- 导言作为web开发人员,我们的生活围绕着数据操作。我们建立数据库来存储数据,写编码来访问和修改数据,设计网页来采集和汇总数据。本文是研究在A
- 1: os.listdir(path) //path为目录 功能相当于在path目录下执行dir命令,返回为list类型 print os.
- 1、表中字段区分大小写的设置在使用gorm查询的时候,会出现账户名A和a是一样的情况,是因为mysql默认不区分大小写造成的1.问题产生的原
- 在transactional replication, 经常会遇到数据同步延迟的情况。有时候这些延迟是由于在publication中执行了一
- 冒泡排序冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们
- 一、下载MySQL 访问MySQL的官网http://www.mysql.com/downloads/&
- 发现问题最近由于卸载Mysql时将很多相关依赖包都卸载了,重装mysql后启动django出现如下错误:django.core.except
- 本文实例讲述了Python编程实现生成特定范围内不重复多个随机数的2种方法。分享给大家供大家参考,具体如下:在近期进行的一个实验中,需要将数
- 在开发的过程中,我们不可避免的会遇到各种各样的编码,解码,或者乱码问题,很多时候,我们可以正常的解决问题,但是说实在的,我们有可能并不清楚问
- 加了三个验证漏洞以及四个getshell方法# /usr/bin/env python3# -*- coding: utf-8 -*-# @
- 研究(2)中讨论了栅格系统的基础知识。这一篇将集中探讨栅格系统的粒度问题。(注:如非特别指明,栅格系统均指24列960栅格系统)淘宝的首页(
- 目录1.代码的编写过程2.结果的可视化展示3.结论前言:前不久,我刷到这样一条短视频,“1.7亿的90后仅有约1000万对结婚,结婚率不到1
- 登录百度AL开发平台在控制台选择语音合成创建应用填写应用信息在应用列表获取(Appid、API Key、Secret Key)6. 安装py
- 一、跨域是什么从一个域名去请求另一个域名,这个过程称之为跨域。浏览器从一个域名的网页去请求另一个域名的资源,域名、端口、协议有一个不一样,请
- 一 前言公司同事最近在做excel相关的工作;今天来求助知识追寻者合并多个excel为一个一个工作本,原本是java操作poi太蛋疼了,笨重
- 引言在观察OpenCV中某个函数在不同参数的情况下,所得到的效果的时候,我之前是改一次参数运行一次,这样做起来操作麻烦,效率低下。为了更便捷
- (在lua中通过loadfile, setfenv实现)python当然也可以:cat config.pybar = 10foo=100ca
- 本文实例为大家分享了Python管理Windows服务的具体代码,供大家参考,具体内容如下#!/usr/bin/python# encodi
- 什么是mock?mock在翻译过来有模拟的意思。它允许您用模拟对象替换您的系统的部分,并对它们已使用的方式进行断言。Mock通常是指,在测试
- 【简 介】熟悉网页设计的网友就知道,调用Style的方法很多,我们可以单击鼠标右键选择Custon Style来调用Style标准,也可以在