django的聚合函数和aggregate、annotate方法使用
支持聚合函数的方法:
提到聚合函数,首先我们要知道的就是这些聚合函数是不能在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中的每个对象生成一个独立的摘要,一定会使用分组,然后再聚合
django的聚合函数和aggregate、annotate方法使用的更多相关文章
- Django 数据聚合函数 annotate
统计各个分类下的文章数 2 周,3 日前 字数 3818 阅读 546 评论 21 在我们的博客侧边栏有分类列表,显示博客已有的全部文章分类.现在想在分类名后显示该分类下有多少篇文章,该怎么做呢?最优 ...
- django ORM聚合函数
在Django中,聚合函数是通过aggregate方法实现的,aggregate方法返回的结果是一个字典 在使用时需要先导入模块from django.db.models import Count,A ...
- aggregate和annotate方法使用详解与示例
aggregate和annotate方法的使用场景 Django的aggregate和annotate方法属于高级查询方法,主要用于组合查询.当我们需要对查询集(queryset)的某些字段进行计算或 ...
- postgresql 自定义聚合函数
方法1 CREATE OR REPLACE FUNCTION public.sfun_test1( results numeric[], val numeric) RETURNS numeric[] ...
- H2Database聚合函数
聚合函数(Aggregate Functions) AVG BOOL_AND BOOL_OR COUNT GROUP_CONCAT MAX MIN SUM SELECTIVITY ST ...
- 【软件实施面试】MySQL和Oracle联合查询以及聚合函数面试总结
软件实施面试系列文章第二弹,MySQL和Oracle联合查询以及聚合函数的面试总结.放眼望去全是MySQL,就不能来点Oracle吗?之前面过不少公司,也做过不少笔试题,现在已经很少做笔试题了.你肚子 ...
- Spark学习之路(十一)—— Spark SQL 聚合函数 Aggregations
一.简单聚合 1.1 数据准备 // 需要导入spark sql内置的函数包 import org.apache.spark.sql.functions._ val spark = SparkSess ...
- Spark 系列(十一)—— Spark SQL 聚合函数 Aggregations
一.简单聚合 1.1 数据准备 // 需要导入 spark sql 内置的函数包 import org.apache.spark.sql.functions._ val spark = SparkSe ...
- 入门大数据---SparkSQL常用聚合函数
一.简单聚合 1.1 数据准备 // 需要导入 spark sql 内置的函数包 import org.apache.spark.sql.functions._ val spark = SparkSe ...
随机推荐
- c++参数传递的三种方式
一般来说C++中参数传递有三种方式:值传递.指针传递.引用传递 1.值传递——传值 值传递是最常见的一种参数传递的方式,但是对初学者来说也最容易出错.如下例: #include<iostream ...
- Spring boot 异常处理配置
1. 新建Maven项目 exception 2. pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0&quo ...
- C语言中volatile关键字的作用[转]
一.前言 1.编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问.另外在现代CPU中指令的执行并不一定严格按照顺序执行,没 ...
- git常用命令(三)
====================================================================== 本地仓库操作 ====================== ...
- 旧文备份:安装cygwin及在console下输入和显示中文
1.下载Cygwin.exe文件,双击安装,首先在"Choose A Download Source"的时候选择"Download Without Installing& ...
- 使用nssm将bat文件注册为windows service (eg:solr, nodejs)
nssm下载:http://pan.baidu.com/s/1sjAEevj _install.bat @echo off Set BasePath=D:\Tools %BasePath%\nssm- ...
- 前端jQuery之属性操作
属性操作主要分为四个部分:html属性操作,dom属性操作,类样式操作和值操作 HTML属性操作:属性的读取,设置,以及移除,如attr().removeAttr() DOM属性操作:属性的读取,设置 ...
- 我是如何根据豆瓣api来理解Restful API设计的
1.什么是REST REST全称是Representational State Transfer,表述状态转移的意思.它是在Roy Fielding博士论文首次提出.REST本身没有创造新的技术.组件 ...
- JS里访问纯数字ID对象时出现问题
<p id="1">Hello</p> 例如上面的例子,id为纯数字会出错.此时用js去获取该对象会报错,查找不到该对象. 原因:必须是字母开头,或是下划线 ...
- Github学生包的申请
Github Education为了大学生们更好的进行开发,进行边做边学,与一些合作伙伴和朋友一起创建GitHub学生开发者包. 里面内容非常丰富,应有尽有: AWS 亚马逊云服务 $75-$150 ...