Django:模型_ORM聚合函数
聚合函数
1、如果使用原生SQL来操作数据库,则可以使用聚合函数来提取数据等。比如提取你某个商品销售的数量,那么可以使用Count函数,如果想要知道商品销售的平均价格,那么可以使用AVG函数
2、在Django的ORM模型中同样可以使用聚合函数来处理数据。在ORM模型中,聚合函数是通过aggregate()等方法来实现的
3、上面第二点的意思为:所有的聚合函数都不能单独的执行,需要放在一些可以执行聚合函数的方法中去执行,比如aggregate()方法
4、所有的聚合函数都是放在"django.db.models"下面的。因此我们在使用聚合函数时,需要导入对应的模块
5、以下例子都是在下面的模型上进行的
例1:模型类
⑴编辑模型
⑵存入数据⑶查看数据
平均值:Avg
作用:返回某一些数据(列)的平均值
例2:
⑵编辑视图
注:上面例子中
1、执行聚合函数后,返回的是一个字典类型的值,如:{'price__avg': 150.0}
⑴聚合函数执行完成后,会自动的给这个计算结果取一个名字。取名的规则默认是:字段(列)名__聚合函数名
⑵如果不想使用Django默认的名字的话,可以在使用聚合函数的时候传递一个关键字参数进去,参数的名字就是聚合函数执行完成的名字
2、aggregate()方法返回的是一个字典类型的值,不是一个QuerySet对象。这个字典中的Key就是聚合函数的名字,值就是聚合函数执行后的结果
3、因为aggregate()方法返回的不是一个QuerySet对象,因此就不能使用"实例名.query"属性来查看聚合函数对应的SQL语句了
⑴只有返回结果是QuerySet对象时,才能使用"实例名.query"属性来查看对应的SQL语句
⑵而是需要使用Django其他的方法来查看:connection.queries。这个方法包含了很多的查询语句列表
4、通过查看上面例子返回的对应的SQL语句,可以看到实际起作用的SQL语句是:SELECT AVG(`book`.`price`) AS `price__avg` FROM `book`'(其他的是Django在执行聚合函数SQL语句前执行的,可以不管)
总数:Count
作用:获取指定的对象的个数
例3:
⑴查看数据
⑵编辑视图:统计有多少个邮箱(包括重复的)
⑶编辑视图:统计有多少个不同的邮箱
最大(小)值:Max和Min
作用:获取执行对象的最大值和最小值
例4:
⑴查看数据
⑵编辑视图
⑶编辑视图
调用聚合函数的aggregate()等方法中可以同时存在多个聚合函数
总和:Sum
作用:求指定对象的总和
例5:
⑴编辑视图
⑵编辑模型
⑶查看数据
⑷链式调用
只要返回的是一个QuerySet对象,那么就可以链式调用聚合函数
F表达式
1、作用:动态获取某个字段上的值(获取后怎么操作就看我们自己了)。并且这个F表达式,不会真正的去数据库中查询,它相当于只是起一个标识的作用
2、F表达式是用来优化ORM操作数据库的
3、F表达式中的参数就是我们需要提取的字段名
例6:
⑴查询执行前的价格
⑵编辑视图
⑶查看执行后的价格
⑷
Q表达式
作用:对对象的复杂查询
例7:
补充:aggregate和annotate
aggregate
1、aggregate:返回使用聚合函数后的字段和值
2、aggregate的中文意思是聚合, 源于SQL的聚合函数。Django的aggregate()方法作用是对一组值(比如queryset的某个字段)进行统计计算,并以字典(Dict)格式返回统计计算结果。django的aggregate方法支持的聚合操作有AVG/COUNT/MAX/MIN/SUM等
annotate
1、annotate:在原来模型字段的基础之上添加一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组(group by)
2、annotate的中文意思是注释,一个更好的理解是分组(Group By)。如果你想要对数据集先进行分组然后再进行某些聚合操作或排序时,需要使用annotate方法来实现。与aggregate方法不同的是,annotate方法返回结果的不仅仅是含有统计结果的一个字典,而是包含有新增统计字段的查询集(queryset).
3、annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)
4、总结:跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询:使用"基于下划线"的查询方式
例8:
⑴编辑模型
⑵存入数据
⑶查看数据
注:
上面新增了一个模型类:用来存储每本图书的订单(图书id和价格),并且该模型内的book属性通过外键关联Book模型类
例9:使用aggregate()方法来实现求订单价格的平均值
⑴编辑视图
例10:使用annotate()方法来实现求每类图书订单价格的平均值
⑴编辑视图
注:
1、在计算"每一本图书的价格"时
⑴最终查询的是:"平均价格",查询的数据在子表中
⑵视图函数中的SQL语句是从"Book"模型类开始的,即从主表(Book)开始的,因此为"反向查询",因此使用的方法为"小写模型名__字段名"
2、不管最终查询的数据是在子表中还是在主表中,只要是从"子表开始查询到主表",那么就是正向查询,"从主表查询到子表就是反向查询"。只是说正向查询和反向查询的写法不一样
⑴外键属性字段定义在哪个模型类中,哪个模型类就是子表
aggregate和annotate的区别
相同点:
这两个方法都可以执行聚合函数
不同点:
⑴aggregate返回的是一个字典,在这个字典中存储的是这个聚合函数执行的结果。而annotate返回的是一个QuerySet对象
⑵aggregate不会做分组,而annotate会使用"group by"子句进行分组,只有调用了"group by"子句才能对每一条数据求聚合函数的值