django-ORM聚合函数
models.py的模型结构
# -*- coding: UTF-8 -*- from django.db import models class Author(models.Model): "作者模型" name = models.CharField(max_length=100) age = models.IntegerField() email = models.EmailField() class Meta: #该名称不能更改 db_table = 'author' #映射到数据库中为你自定义的名字,不设置这个默认为 包名_表名 映射到数据库 class Publisher(models.Model): "出版社模型" name = models.CharField(max_length=300) class Meta: db_table = 'publisher' class Book(models.Model): "book模型" name = models.CharField(max_length=300) pages = models.IntegerField() price = models.FloatField() rating = models.FloatField() author = models.ForeignKey(Author,on_delete = models.CASCADE) publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE) class Meta: db_table = 'book' class BookOrder(models.Model): "图书订单模型" book = models.ForeignKey("Book",on_delete=models.CASCADE) price = models.FloatField() class Meta: db_table = 'book_order'
聚合函数
在views.py中
1.Avg : 求平均值
from django.shortcuts import render from django.http import HttpResponse from .models import Book from django.db.models import Avg from django.db import connection def index(request): #获取book表下的价格(price字段)求平均价(平均值) result = Book.objects.aggregate(Avg('price')) #Avg不能直接使用,需要使用aggregate包住 print(result) print(connection.queries) #可以查看被翻译成的sql语句,需要导入connection, 如果是queryset的话就可以使用query进行查询 return HttpResponse('index')
这时候django就会自动给你创建一个别名,也就是 字段名__Avg,如果想要更给改的话
#这时候django就会自动给你创建一个别名,也就是 字段名__Avg,如果想要更给改的话 result = Book.objects.aggregate(price_avg=Avg('price')) #Avg不能直接使用,需要使用aggregate包住
关于 aggregate 和 annotate 执行聚合函数的方法
例子 : 比如在求平均值 #1.aggregate 会将所有的值都会求出平均值(需要导入connection模块) def index(request): result = Book.objects(Avg('price')) #Avg不能直接使用,需要使用aggregate包住详情看1的写法
print(result)
#2.annotate 的话就会一个额外的 group by的分组操作,然后在求出各个组的平均值 #求各组的平均值 #将Book表下关联的BookOrder(使用的话就django默认设置的小写)的price字段中根据id的不同分组,然后在求出各个组的平均值
books = Book.objects.annotata(price_avg=Avg('bookorder__price')) #将这个名称改了price_avg
for book in books: print('%s/%s'%(book.name,book.price_avg)) #price_avg在前面中已经更改了名称,不然就是默认的Avg
Count 求每个表中有多少个id(也就是求总数)
from django.http import HttpResponse from .models import Book,Author,BookOrder from django.db.models import Avg,Count from django.db import connection #1. Count 求每个表中有多少个id(也就是求总个数) # result = Book.objects.aggregate(book_nums =Count('id')) #book_nums自定义关键字参数,用户接收返回的数据 # print(result) # print(connection.queries) #查看转换成的sql语句 #2.统计 Author 表下的有多少个不同的邮箱(也就是使用count统计相同的邮箱时只算一个,而不是全部统计)- 也就是distinct=True # result = Author.objects.aggregate(email_nums =Count('email',distinct=True)) #email_nums自定义关键字参数,用户接收返回的数据 # print(result) # print(connection.queries) #查看转换成的sql语句 # 3. 使用 annotate 来统计每个分组的具体个数( 换言之也就是求每个组的销量等等这样的就可以使用这个方法 ) books = Book.objects.annotate(book_nums=Count('bookorder__id')) #bookorder__id 也就是bookorder表下的id字段 for book in books: print('%s/%s'%(book.name,book.book_nums)) #使用了book_nums自定义参数那么这个表就自动增加了这个属性
Max 和 Min 获取指定对象(某字段)的最大值和最小值
from django.db.models import Avg,Count,Max,Min # 1. Max 和 Min 获取指定对象(某字段)的最大值和最小值 result = Author.objects.aggregate(max=Max('sge'),min=Min('age')) #求这个Author表下的年龄字段的最大值和最小值,max和min是自定义的,用来接收值 print(request) print(connection.queries) #同理也可以使用annogate分组求每本书的最大值和最小值
Sum : 求某个字段的总和
from .models import Book,Author,BookOrder from django.db.models import Avg,Count,Max,Min,Sum #如果有漏的在自行导入,这只是一个大概例子 #1. 求所有图书的销售总额,也就是所有卖出的书的总和 # result = BookOrder.objects.aggregate(total=Sum('price')) #求出BookOrder表下price字段的总和 # print(request) # print(connection.queries) #2. 单独求出每一本书的销售总额(也就是关于三国演义这本书以及红楼梦这本书都各卖了多少钱)-需要到分组也就是 annotate books = BookOrder.objects.annotate(total=Sum('bookorder__id')) #对bookorder__id这个字段做一个分组,然后求出每个分组的总额,然后使用自定义的total接收 for book in books: print('%s%s'%(book.name,book.total)) #这个total是上面自定义的,自定义好厚就会为这个表添加上这个属性 print(connection.queries) #3.求某一年的销售总额 - 这里只提供思路 # ①先获取某一年的数据 表名.objects.filter 回顾之前的时间查询条件 # ②再根据这些数据使用Sum求出来即可 ,使用正常的 aggregate 和 Sum #4.求每一种书在某一年的销售总额,也就是三国演义在2018年一共卖了多少钱,红楼梦在2015一共卖了多少钱 #①先获取某一年的数据 表名.objects.filter 回顾之前的时间查询条件 #②再根据这些数据使用Sum求出来即可 ,使用正常的 annotate 和 Sum