06-模型层8—多表操作之多表下的分组查询

一、基于多表的“分组查询”

这里以Book表与Publish表为例,表关系字段在Book中定义。

1、查询每一个出版社出版的书籍的个数

##后面这引入段省略
from django.db.models import Avg,Max,Min,Count

##查询每一个出版社出版的书籍的个数
ret = Book.objects.values('publish_id').annotate(Cout('title'))
print(ret)

2、查询每一个出版社的名称以及出版书籍的个数

(1)SQL方法:

select publish.name,Count('title') from book inner join publish 
on book.publish_id = publish.nid
group by publish_nid

(2)annotate方法:

————注意,Publish查Book是反向查询,按“表名”

A:
    ret = Publish.objects.values('name').annotate(count=Count('book__title'))
    print(ret) #<QuerySet [{'name': '苹果出版社', 'count': 1}, {'name': '333', 'count': 4}]>
###############################################################################
B:  
    ret = Publish.objects.values('name').annotate(count=Count('book__title')).values('name', 'count')
    print(ret) #<QuerySet [{'name': '苹果出版社', 'count': 1}, {'name': '333', 'count': 4}]>

3、查询每一个作者的名字以及出版过的书籍的最高价格

(1)SQL方法

select author.name,Max(book.price) from book inner join book_authors
on book.nid = book_authors.book_id
inner join author 
on autohr.nid = book_authors.author_id
group by author.nid

(2)annotate方法

注意主键可以用 pk 表示;Author找Book是“反向查询”按表名小写

ret = Author.objects.values('pk').annotate(max_price=Max('book__price')).values('name','max_price')
print(ret) 
#<QuerySet[{'name':'whw','max_price':Decimal('200.00')},{'name':'www','max_price': Decimal('200.00')}]>

4、查询每一个书籍的名称以及对应的作者的个数

————“正向查询按字段”

ret = Book.objects.values('pk').annotate(c=Count('authors__name')).values('title','c')
print(ret) #<QuerySet [{'title': '三国群英传', 'c': 1}, {'title': '三国群英', 'c': 2}, {'title': '金瓶', 'c': 0}, {'title': '水浒传', 'c': 0}, {'title': '金瓶', 'c': 0}]>

二、小结

1、多表下的分组查询语法(注意是values不是filter):

#注意以哪张表中的字段分组,哪一张表就是“后表”
每一个后表模型.objects.values('pk').annotate(聚合函数('关联表__统计字段')).values('表模型的所有字段以及统计字段')

2、另一种写法:

每一个后表模型.objects.annotate(聚合函数('关联表__统计字段')).values('表模型的所有字段以及统计字段')
这种写法等价于
每一个后表模型.objects.all().annotate(聚合函数('关联表__统计字段')).values('表模型的所有字段以及统计字段')

三、几个练习

1

统计每一本以“三”字开头的书籍的作者的个数————Book找Author是多对多,而且是“正向查询”按字段

ret = Book.objects.filter(title__startswith='三').annotate(c=Count('authors__name')).values('title','c')
print(ret) 
#<QuerySet [{'title': '三国群英传', 'c': 1}, {'title': '三国群英', 'c': 2}]>

2

统计不止一个作者的书籍的名字————Book找Author是多对多,而且是“正向查询”按字段

ret = Book.objects.values('pk').annotate(num_authors=Count('authors__name')).filter(num_authors__gt=1).values('title','num_authors')
print(ret)

3

根据一本图书作者数量的多少对查询集 QuerySet进行排序:

Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')

4

查询各个作者出的书的总价格

#按author表的所有字段 group by
queryResult=Author.objects
                    .annotate(SumPrice=Sum("book__price"))
            .values_list("name","SumPrice")
print(queryResult)
posted on 2019-05-19 11:11  江湖乄夜雨  阅读(147)  评论(0编辑  收藏  举报