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
扫描二维码关注公众号,回复: 7961750 查看本文章

猜你喜欢

转载自www.cnblogs.com/ifdashui/p/11914776.html