annotate和aggregate的区别

一. 基本区别

  1. aggregate:返回使用聚合函数后的字段和值。
  2. annotate:在原来模型字段的基础之上添加一个使用了聚合函数的字段

二. 使用方法

class Book(models.Model):
     """图书模型"""
     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 BookOrder(models.Model):
     """图书订单模型"""
     book = models.ForeignKey("Book",on_delete=models.CASCADE)
     price = models.FloatField()
    
    
class Author(models.Model):
     """作者模型"""
     name = models.CharField(max_length=100)
     age = models.IntegerField()
     email = models.EmailField()



1.Avg:求平均值。

比如想要获取所有图书的价格平均值

 from django.db.models import Avg
 result = Book.objects.aggregate(Avg('price'))
 print(result)

输出为

 {"price__avg":23}

其中price__avg的结构是根据field__avg规则构成的。如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数。比如my_avg=Avg('price'),那么输出为

 {"my_avg":23}



2.Count:获取指定的对象的个数

比如想获得所有图书的数量

from django.db.models import Count
result = Book.objects.aggregate(book_num=Count('id'))

Count类中,还有另外一个参数叫做distinct,默认是等于False,如果是等于True,那么将去掉那些重复的值。比如要获取作者表中所有的不重复的邮箱总共有多少个,那么可以通过以下代码来实现:

from djang.db.models import Count
result = Author.objects.aggregate(count=Count('email',distinct=True))



3.Sum:求指定对象的总和

比如要求图书的销售总额

from djang.db.models import Sum
result = Book.objects.annotate(total=Sum("bookorder__price")).values("name","total")

annotate的意思是给Book表在查询的时候添加一个字段叫做total,这个字段的数据来源是从BookOrder模型的price的总和而来。values方法是只提取nametotal两个字段的值。

注意:Sum和Count的区别

count()函数里面的参数是列名的的时候,那么会计算有值项的次数,即使值为空字符串也会计算。

而sum里面的参数是列名的时候,是计算列名的值的相加

比如,把所有机构按在线设备数进行排序

机构(org)是设备(device_detail)的主键;设备在线值为"1", 不在线值为"0"

 orgs = org.objects.annotate(online_num=Sum('device_detail__online')).order_by('-online_num')

这里如果用Sum,那么是按机构的在线设备数进行排序

如果用Count, 那么会按机构所拥有的总设备数进行排序



4.MaxMin:获取指定对象的最大值和最小值。

比如想要获取Author表中,最大的年龄和最小的年龄分别是多少

from django.db.models import Max,Min
result = Author.objects.aggregate(Max('age'),Min('age'))

输出为

 {"age__max":88,"age__min":18}



5.分组

比如获取DM中每个在线设备,每一个型号的设备数

device_detail表是device的外键表,online是device_detail中的字段,model是device表中的字段

from django.db.models import Count

online_devices_model=device.objects.filter(device_detail__online=1).values('model').annotate(model_num=Count('model')) 

返回值如下

>>> online_devices_model
<QuerySet [{'model': 'IR7XX_EVDO/CDMA', 'model_num': 131}, {'model': 'InDTU3XX_GPRS/EDGE', 'model_num': 3152},...
posted @ 2022-12-02 15:13  坚强的小蚂蚁  阅读(168)  评论(0编辑  收藏  举报