十六.聚合查询 aggregate( *args,**kwargs)
1.五种聚合函数
- Avg (Average) : 平均值
- Max (Maximum) : 最大值
- Min (Minimum) : 最小值
- Sum (Summary) : 求和
- Count : 个数
2.aggregate( )
aggregate()
是QuerySet
的一个终止子句,意思是说,它返回一个包含一些键值对的字典- 键的名称是聚合值的标识符,值是计算出来的聚合值
- 键的名称是按照字段和聚合函数的名称自动生成出来的
- 如果你想要为聚合值指定一个名称,可以向聚合子句提供它
from django.db.models import Avg,Max,Min,Sum,Count # 导入聚合函数
res = models.Book.objects.aggregate(Avg('price'))
print(res) # {'price__avg': Decimal('34.204000')}
res = models.Book.objects.aggregate(avg_price=Avg('price')) # 指定名称
print(res) # {'avg_price': Decimal('34.204000')}
3.示例
- 求所有数据价钱最高的, 最低的, 总和, 平均价钱
from django.db.models import Max,Min,Sum,Avg
res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Avg('price'))
print(res) # {'price__max': Decimal('88.88'), 'price__min': Decimal('6.66'), 'price__sum': Decimal('171.02'), 'price__avg': Decimal('34.204000')}
ps : 聚合查询一般配合分组查询一起使用
十七.分组查询 annotate
以字段为依据将相同的分为一类, annotate( )
内写聚合函数
1.分组依据
- values( ) 在 annotate( ) 之前则表示 group by 字段
# 默认分组依据
如果 annotate() 直接跟在 objects 后面,则表示直接以当前的基表为分组依据
例 : 按书来分组 : odels.Book.objects.annotate(sum_price=Sum)
# 指定分组依据
如果 annotate() 跟在 values() 后面,则表示按照values中指定的字段来进行分组
例 : 按照书中的price进行分组 : models.Book.objects.values('price').annotate()
- values( ) 在 annotate( ) 之后则表示取字段
- filter( ) 在 annotate( ) 之前则表示 where 条件
- filter( ) 在 annotate( ) 之后则表示 having 条件
2.示例:
# from django.db.models import Max,Min,Sum,Avg
# 查询出版社id大于1的出版社id,以及出书平均价格
res = models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(avg_price=Avg('price')).values('publish_id','avg_price')
print(res) # <QuerySet [{'publish_id': 2, 'avg_price': Decimal('31.635000')}, {'publish_id': 3, 'avg_price': Decimal('9.435000')}]>
# 查询出版社id大于1的出版社id,以及出书平均价格大于25的
res = models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(avg_price=Avg('price')).filter(avg_price__gt=25).values('publish_id','avg_price')
print(res) # <QuerySet [{'publish_id': 2, 'avg_price': Decimal('31.635000')}]>
# 查询每一个出版社出版的名称和书籍个数(连表)(连表最好以group by的表作为基表)
res = models.Publish.objects.annotate(count_book=Count('book')).values('name','count_book')
print(res) # <QuerySet [{'name': '沙河尚出版社', 'count_book': 1}, {'name': '北京出版社', 'count_book': 2}, {'name': '狗不理出版社', 'count_book': 2}]>
# 上面以Book作为基表
res = models.Book.objects.values('publish_id').annotate(book_count=Count('nid')).values('publish__name','book_count')
print(res) # <QuerySet [{'publish__name': '沙河尚出版社', 'book_count': 1}, {'publish__name': '北京出版社', 'book_count': 2}, {'publish__name': '狗不理出版社', 'book_count': 2}]>
# 查询每个作者的名字,以及出版过书籍的最高价格(建议使用分组的表作为基表)
# 多对多如果不以分组的表作为基表, 可能会出现数据问题
res = models.Author.objects.annotate(max_price=Max('book__price')).values('name','max_price')
print(res) # <QuerySet [{'name': 'shawn', 'max_price': Decimal('88.88')}, {'name': 'chris', 'max_price': Decimal('88.88')}, {'name': '小rub', 'max_price': Decimal('55.50')}, {'name': 'summer', 'max_price': Decimal('12.21')}]>
res = models.Book.objects.values('authors__nid').annotate(max_price=Max('price')).values('authors__name','max_price')
print(res) # <QuerySet [{'authors__name': 'shawn', 'max_price': Decimal('88.88')}, {'authors__name': 'chris', 'max_price': Decimal('88.88')}, {'authors__name': '小rub', 'max_price': Decimal('55.50')}, {'authors__name': 'summer', 'max_price': Decimal('12.21')}]>
# 查询每一个书籍的名称, 以及对应的作者个数
res = models.Book.objects.annotate(auth_count=Count('authors__nid')).values('title','auth_count')
print(res) # <QuerySet [{'title': '北京爱情故事', 'auth_count': 2}, {'title': '水浒传', 'auth_count': 2}, {'title': '三国演义', 'auth_count': 1}, {'title': '红楼梦', 'auth_count': 3}, {'title': '包子秘籍', 'auth_count': 2}]>
# 统计价格25元, 作者个数大于1的图书
res = models.Book.objects.filter(price__gt=25).annotate(auth_count=Count('authors__nid')).values('title','auth_count','price')
print(res) # <QuerySet [{'title': '北京爱情故事', 'price': Decimal('88.88'), 'auth_count': 2}, {'title': '红楼梦', 'price': Decimal('55.50'), 'auth_count': 3}]>
十八. F 查询
1.F 查询介绍
- 我们之前的例子中对一些字段的过滤和操作都是与一个常量进行比较大小, 如果我们想让字段与字段的值进行比较就无法简单实现, 于是就可以使用 F 查询了
- 作用 : 取出某个字段对应的值
2.使用示例:
from django.db.models import F,Q # 先导入
# 查询评论数大于阅读数的书籍
res = models.Book.objects.filter(commit_num__gt=f('read_num'))
# 将所有图书价格+5块
res = models.Book.objects.update(price=F('price')+5)
print(res) # 5 (影响条数)
十九. Q 查询
1.Q查询介绍
- filter 的字段筛选条件如果指定多个, 默认是and连接多个条件, 如果想要使用or或者not,则需要Q查询
- 作用 : 构造
或 or
、与 &
、非 ~
条件