聚合查询 aggregate( *args,**kwargs)
1.基本介绍
介绍:聚合查询通常情况下都是配合分组一起使用的. 如果你只想使用聚合函数, 但是不想分组, 那么就应该使用aggregate.
使用:直接在objects后面链接.
返回:返回字典格式的数据. 如果是对price字段求平均值, 那么返回格式是: {'price__avg': 值}
和数据库相关模块的方法: 基本是都在django.db.models里面 如果上述没有那么应该在django.db里面
2.五种聚合函数
- Avg (Average) : 平均值
- Max (Maximum) : 最大值
- Min (Minimum) : 最小值
- Sum (Summary) : 求和
- Count : 个数
3.aggregate()
aggregate()
是QuerySet
的一个终止子句,意思是说,它返回一个包含一些键值对的字典- 键的名称是聚合值的标识符,值是计算出来的聚合值
- 键的名称是按照字段和聚合函数的名称自动生成出来的
- 如果你想要为聚合值指定一个名称,可以向聚合子句提供它
from django.db.models import Avg,Max,Min,Sum,Count # 导入聚合函数 res = models.Book.objects.aggregate(Avg('price')) print(res) res = models.Book.objects.aggregate(avg_price=Avg('price')) # 指定名称 print(res) res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Avg('price')) print(res)
分组查询 annotate
1.介绍
分组注意事项
-
分组只能拿到分组的依据. 按照什么分组就只能拿到什么组. 其他字段不能直接获取, 需要借助一些方法(聚合函数)
-
提示: 可以指定多个分组, 指定多个分组, 当然就可以获取多个分组之间的分组依据.
如果执行orm分组查询报错,并且有关键字sql_mode strict mode 移除sql_mode中的only_full_group_by
步骤:
第一步: 指定分组的依据 第一种情况: 默认分组. annotate直接在objects后面链接时, models后面点什么就按照什么分组. 例子: 按照书分组 models.Book.objects.annotate(sum_price=Sum) 第二种情况: 指定分组. annotate跟在values后面, values中指定什么字段就按照什么分组 例子: 按照书中的价格分组. models.Book.objects.values('price').annotate() 第二步: 为分组的字段取别名 第三步: 在annotate后面使用values可以获取分组的依据和分组之后的结果
返回:返回QuerySet对象
2.分组依据
- 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 条件
3.示例
# 分组查询 # 统计每一本书的作者个数 res = models.Book.objects.annotate(authors_num=Count('authors__pk')).values('title','authors_num') print(res) # 统计出每个出版社卖的最便宜的书的价格 res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price') print(res) # 统计不止一个作者的图书 # 第1步:先统计每本书的作者个数 author_num = models.Book.objects.annotate(authors_num=Count('authors__pk')) # 第2步:筛选出作者个数大于1的图书 res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('title','author_num') print(res) # 查询每个作者出的书的数量和总价格 res = models.Author.objects.annotate(total_num=Count('book__pk'),total_price=Sum('book__price'),).values('name','total_num','total_price') print(res) """按照字段分组""" # 统计每个出版社所出的书的数量 res = models.Book.objects.values('publish_id').annotate(total_num=Count('pk')).values('publish__name','total_num') print(res)
F与Q查询
数据准备
往之前的书籍表中插入两条数据——库存量和卖出数。
第一次修改数据之后都得执行数据迁移的操作,往已有数据的表格中插入数据,执行数据迁移时无法成功,需要设置参数,不然无法添加。有两种方法:
1. 设置默认值:default = 默认数值
2. 允许为空:null = True
"""后续添加两个字段""" stock = models.IntegerField(verbose_name='库存数',default=1000) # 设置默认值 sold = models.IntegerField(verbose_name='卖出数',null=True) # 允许为空
F查询介绍
- 我们之前的例子中对一些字段的过滤和操作都是与一个常量进行比较大小, 如果我们想让字段与字段的值进行比较就无法简单实现, 于是就可以使用 F 查询了
- 作用 : 取出某个字段对应的值
使用示例
""" # 作用: 能够帮助你直接获取到表中某个字段对应的数据 # 使用: from django.db.models import F # 获取到某个字段对应的数据 F("字段__条件") # 查询字段对应的数据是数字类型可以直接加减运算: F('字段__条件') + 500 # 字符类型需要借助Concat和Value方法 from django.db.models.functions import Concat from django.db.models import Value Concat(F('字段__条件'), Value("str")) 注意: 查询字段对应的数据是字符类型不能直接进行拼接. 否则操作的字段对应的所有数据将变成空白. """ # 查询库存数大于卖出数的书籍 from django.db.models import F res = models.Book.objects.filter(stock__gt=F('sold')) print(res) # 将所有书的价格涨80元 models.Book.objects.update(price=F('price')+80) # 将所有书的名称后面都追加”爆款“两个字 from django.db.models.functions import Concat from django.db.models import Value models.Book.objects.update(title=Concat(F('title'),Value('爆款')))
Q查询
Q查询介绍
- filter 的字段筛选条件如果指定多个, 默认是and连接多个条件, 如果想要使用or或者not,则需要Q查询
- 作用 : 构造
或 or
、与 &
、非 ~
条件
示例
""" # 作用: filter的字段筛选条件指定多个, 默认是and连接. 要实现or或者not需要借助Q查询 # 使用: from django.db.models import Q Q(字段__条件=值) # 连接条件and的3种情况 1. filter中指定多个参数逗号隔开: filter(参数1, 参数2) 2. 查询指定多个逗号隔开: filter(Q(), Q()) 3. 使用&连接符: filter(Q() & Q()) # 连接条件or filter(Q() | Q()) # 连接条件not filter(~Q() | Q()) # Q查询的高阶用法: 让左边指定的变量形式的查询条件可以是字符串 q = Q() q.connecter = 'or' # 指定连接符. 不指定默认and q.children.append(Q('字段__条件', 值)) res = models.XXX.objects.filter(q) """ from django.db.models import Q # 1. 查询卖出数大于100 和 价格小于900的书籍 --> 连接条件 and # res = models.Book.objects.filter(sale__gt=100, price__lt=900) # res = models.Book.objects.filter(Q(sale__gt=100), Q(price__lt=900)) res = models.Book.objects.filter(Q(sale__gt=100) & Q(price__lt=900)) print(res) # 2. 查询卖出数大于100或者价格小于600的书籍 --> 连接条件 or res = models.Book.objects.filter(Q(sale__gt=100) | Q(price__lt=600)) print(res) # 3. 查询卖出数不大于100或者价格小于600的书籍 --> 连接条件 not res = models.Book.objects.filter(~Q(sale__gt=100) | Q(price__lt=600)) print(res) # 4. Q的高阶用法: 能够将查询条件的左边变量的形式变成字符串的形式 q = Q() # 第一步: 实例化一个q对象 q.connector = 'or' # 第二步: 定义连接条件 q.children.append(('sale__gt', 100)) # 第三步: 指定字符串形式的查询字段条件, 以及范围100 q.children.append(('price__lt', 600)) res = models.Book.objects.filter(q) # 第四步: 将q对象传入filter print(res)
标签:__,聚合,models,res,price,查询,objects,分组 From: https://www.cnblogs.com/chen-ao666/p/16989357.html