一、分组查询
select谁就annotate谁,group by谁就values谁,之后要啥再通过values拿啥
语法模型:
后表模型.objects.values(‘pk’).annotate(聚合函数(关联表__字段)).values(表模型所有字段以及统计字段)
后表模型.objects.annotate(聚合函数(关联表__字段)).values(表模型所有字段以及统计字段)==后表模型.objects.all().annotate(聚合函数(关联表__字段)).values(表模型所有字段以及统计字段)
先连接表,再分组查询
练习一:
查询每一个出版社出版的名称以及书籍个数
SQL连接表:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
SELECT * FROM app_book INNER JOIN app_publish on app_book.publish_id = app_publish.nid
ORM连接表:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Book.objects.values("publish").values()
SQL链表后分组:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
SELECT count(title),app_publish.name FROM app_book INNER JOIN app_publish on app_book.publish_id = app_publish.nid GROUP BY publish_id
ORM链表后分组,方式一:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Publish.objects.values("name").annotate(Count("book__title"))
ORM链表后分组,方式二:
通过values拿所需数据即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Publish.objects.values("nid").annotate(c=Count("book__title")).values('name',"c")
练习二:
查询每一个作者的名字以及出版过的书籍的最高价格
SQL语法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
SELECT app_author.name,max(price) FROM app_author INNER JOIN app_book_authors ON app_author.nid = app_book_authors.author_id INNER JOIN app_book ON app_book_authors.book_id = app_book.nid ORDER BY app_author.nid
ORM操作:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Author.objects.values("nid").annotate(max_price=Max("book__price")).values('name',"max_price")
练习三:
每本书籍的名称以及对应的作者个数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Book.objects.values("nid").annotate(c=Count("authors__name")).values('title','c')
练习四:
统计每一本以红开头的书籍的作者个数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Book.objects.filter(title__startswith="红").annotate(c=Count("authors__nid")).values('title','c')
练习五:
统计不止一个作者的书籍
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Book.objects.values('nid').annotate(c=Count("authors__nid")).filter(c__gt=1).values('title','c')
扩展分组查询方法:
同时group by多个字段,即多个字段同时相同才作为一个分组
ORM对all()进行分组,需要什么字段,用values取相应字段即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Book.objects.all().annotate(c=Count("authors__name")).values('title','c')
二、F查询与Q查询
相当于where里面添加多个条件
Q:
和:&
或:|
Q前面添加~表示取反
可以Q里面再嵌套Q
filter()中,Q与键值对可以同时存在,但键值对一定放在Q之后
需求一:查询评论数大于阅读数的书籍
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db.models import F res=Book.objects.filter(comment_num__gt=F("read_num"))
需求二:批量更新书籍价格,在当前价格上加10
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db.models import F Book.objects.all().update(price=F("price")+10)
需求三:查询书籍名称为“红楼梦”或评论数等于100的书籍
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db.models import Q Book.objects.filter(Q(comment_num=100)|Q(title="红楼梦"))