Django(18)聚合函数
前言
orm模型中的聚合函数跟MySQL中的聚合函数作用是一致的,也有像Sum
、Avg
、Count
、Max
、Min
,接下来我们逐个介绍
聚合函数
所有的聚合函数都是放在django.db.models
下面。并且聚合函数不能够单独的执行,聚合函数是通过aggregate
方法来实现的。在说明聚合函数的用法的时候,都是基于以下的模型对象来实现的。
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):
"""图书模型"""
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'
Avg
Avg:求平均值。比如想要获取所有图书的价格平均值。那么可以使用以下代码实现。
from django.db.models import Avg
result = Book.objects.aggregate(Avg('price'))
print(result)
以上的打印结果是:
{"price__avg":23.0}
其中price__avg
的结构是根据field__avg
规则构成的。如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数。示例代码如下:
from django.db.models import Avg
result = Book.objects.aggregate(my_avg=Avg('price'))
print(result)
以上的打印结果为
{"my_avg":23}
Count
Count:获取指定的对象的个数。示例代码如下:
from django.db.models import Count
result = Book.objects.aggregate(book_num=Count('id'))
以上的result将返回Book表中总共有多少本图书。
Count
类中,还有另外一个参数叫做distinct
,默认是等于False
,如果是等于True
,那么将去掉那些重复的值。比如要获取作者表中所有的不重复的邮箱总共有多少个,那么可以通过以下代码来实现:
from djang.db.models import Count
result = Author.objects.aggregate(count=Count('email',distinct=True))
Max和Min
Max和Min:获取指定对象的最大值和最小值。比如想要获取Author
表中,最大的年龄和最小的年龄分别是多少。那么可以通过以下代码来实现:
from django.db.models import Max,Min
result = Author.objects.aggregate(Max('age'),Min('age'))
如果最大的年龄是90,最小的年龄是10。那么以上的result将为:
{"age__max":90,"age__min":10}
Sum
Sum:求指定对象的总和。比如要求图书的销售总额。那么可以使用以下代码实现:
from djang.db.models import Sum
result = Book.objects.annotate(total=Sum("bookorder__price"))
以上的代码annotate
的意思是给Book
表在查询的时候添加一个字段叫做total
,这个字段的数据来源是从BookOrder
模型的price
的总和而来。
aggregate和annotate的区别
- 相同点:这两个方法都可以执行聚合函数。
- 不同点:
aggregate
返回的是一个字典,在这个字典中存储的是这个聚合函数执行的结果。而annotate
返回的是一个QuerySet
对象,并且会在查找的模型上添加一个聚合函数的属性。aggregate
不会做分组,而annotate
会使用group by
子句进行分组,只有调用了group by
子句,才能对每一条数据求聚合函数的值。
F表达式:
F表达式: 动态的获取某个字段上的值。并且这个F表达式,不会真正的去数据库中查询数据,他相当于只是起一个标识的作用。比如想要将原来每本图书的价格都在原来的基础之上增加10元,那么可以使用以下代码来实现:
from django.db.models import F
Book.objects.update(price=F("price")+10)
Q表达式
Q表达式:使用Q表达式包裹查询条件,可以在条件之间进行多种操作。与/或非等,从而实现一些复杂的查询操作。例子如下:
- 查找价格大于100,并且评分达到4.85以上的图书:
# 不使用Q表达式的
books = Book.objects.filter(price__gte=100,rating__gte=4.85)
# 使用Q表达式的
books = Book.objects.filter(Q(price__gte=100)&Q(rating__gte=4.85))
- 查找价格低于100元,或者评分低于4分的图书:
books = Book.objects.filter(Q(price__gte=100)&Q(rating__gte=4.85))
- 获取价格大于100,并且图书名字中不包含”传“字的图书:
books = Book.objects.filter(Q(price__gte=100)&~Q(name__icontains='传'))