day057聚合分组查询(接多表查询)

本节内容:接多表操作

1、聚合查询与分组查询
2、F查询与Q查询

一、聚合查询与分组查询

1、聚合

aggregate(*args, **kwargs)
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。

键的名称是聚合值的标识符,值是计算出来的聚合值。

键的名称是按照字段和聚合函数的名称自动生成出来的。

如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
fe1:计算所有图书的平均价格
from django.db.models import Avg Book.objects.all().aggregate(Avg('price')) # {'price__avg': 34.35} 
Python
Copy
fe2:查询学生总人数
models.Student.objects.all().aggregate(c=Count('*')) 
Python
Copy
1、如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。
所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
from django.db.models import Avg, Max, Min >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} 
Python
Copy

2、分组查询

1、单表分组查询
#查询每一个部门名称以及对应的员工数

sql:
    select dep,Count(*) from emp group by dep; select dep,AVG(salary) from emp group by dep; orm: queryset=models.Emp.objects.values("dep").annotate(c=Count("*")) ''' from django.db.models import Avg,Count,Max,Min # 查询每一个部门的人数 # queryset=models.Emp.objects.values("dep").annotate(c=Count("*")) # print(queryset) # <QuerySet [{'dep': '销售部', 'c': 1}, {'dep': '人事部', 'c': 2}]> # # # 查询每一个省份的平均薪水 # queryset=models.Emp.objects.values("province").annotate(avg_salary=Avg("salary")) # print(queryset) # <QuerySet [{'province': '山东', 'avg_salary': 4500.0}, {'province': '河北', 'avg_salary': 5000.0}]> 
Python
Copy
2、多表分组查询
annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。 
# 1 查询每一个出版社的名字和出版过的书籍的平均价格
'''
-- sql语句:
SELECT app01_publish.name,AVG(app01_book.price) from app01_book LEFT JOIN app01_publish on
                         app01_book.publish_id = app01_publish.id
                         group by app01_publish.id,app01_publish.name
'''

# queryset=models.Publish.objects.values("id","name").annotate(avg_price=Avg("book__price"))
# queryset=models.Publish.objects.values("id","name","email","city").annotate(avg_price=Avg("book__price")) # [{"id":1,"name":"苹果出版社","eamil":"123","city":"beijing",'avg_price': 119.0},{"id":1,"name":"橘子出版社","eamil":"123","city":"beijing",'avg_price': 155.333333.0}] # queryset=models.Publish.objects.all().annotate(avg_price=Avg("book__price")) # print(queryset) #<QuerySet [<Publish: 苹果出版社>, <Publish: 橘子出版社>]> # for obj in queryset: # print(obj.name,obj.avg_price) # 2 查询每一个作者的名字以及出版书籍的个数 queryset=models.Author.objects.annotate(c=Count("book")).values("name","c") print(queryset) # <QuerySet [{'name': 'alex', 'c': 2}, {'name': 'egon', 'c': 2}]> # 3 查询每一个书籍的名称以及作者的个数 queryset=models.Book.objects.annotate(c=Count("authors")).values("title","c") print(queryset) # 4 查询作者个数大于1 的每一本书籍的名称和作者个数 queryset=models.Book.objects.annotate(c=Count("authors")).filter(c__gt=1).values("title","c") print(queryset) # <QuerySet [{'title': 'python', 'c': 2}, {'title': 'go', 'c': 2}]> # 5 查询书籍名称包含"h"的书籍名称和作者个数 queryset=models.Book.objects.filter(title__contains="h").annotate(c=Count("authors")).values("title","c") 
Python
Copy

二、F查询与Q查询

1、F查询(作用:用于比较两个字段的值)

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。

如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。
F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
# F查询(仅可以对数值操作)  用于单表查询,涉及到两个变动的值进行对比,就要使用F查询
from django.db.models import F,Q,Avg # 1、查询评论数大于100的文章 # queryset=models.Article.objects.filter(comment_num__gt=100) # print(queryset) # 2、查询评论数大于点赞数的文章 # queryset=models.Article.objects.filter(comment_num__gt=F("poll_num")) # # 本来要写一个固定的数字,用F以后就可以使用一个变动的值 # print(queryset) # 3、查询点赞数大于两倍的评论数的文章 # queryset=models.Article.objects.filter(poll_num__gt=F("comment_num")*2) # print(queryset) # 对F得到的结果可以在进行数据运算 # 4、将所有的书籍的价格提高100元 # models.Book.objects.all().update(price=F("price")+100) # print("???????你好") 
Python
Copy

2、Q查询(filter方法中,运用与或非)

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。
如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
& | ~  对应 与或非
# Q查询  可以通过与或非,将各种条件组合起来

# 5、查询价格大于300或者书籍名字以p开头的书籍
queryset=models.Book.objects.filter(price__lt=30) # queryset=models.Book.objects.filter(Q(title__startswith="p") | Q(price__gt=30)) # print(queryset) # 6、查询价格大于300或者不是2019年1月份的书籍 # q=Q(price__gt=300)|~Q(Q(pub_date__year=2019)&Q(pub_date__month=1)) # queryset=models.Book.objects.filter(q) # print(queryset) # F与Q联合查询, # 点赞大于评论数的文章或者是评论数超过200文章 queryset=models.Article.objects.filter(Q(poll_num__gt=F("comment_num"))|Q(comment_num__gt=200)) print(queryset) 
Python
Copy
1、查询函数可以混合使用Q 对象和关键字参数。
所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。
但是,如果出现Q 对象,它必须位于所有关键字参数的前面。
例如:
bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017), title__icontains="python" )

转载于:https://www.cnblogs.com/yipianshuying/p/10252581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值