方法用聚合函数)。
总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询,,既然是join连表,就可以使用咱们的双下划线进行连表了。
#单表:
#查询每一个部门的id以及对应员工的平均薪水
ret = models.Emp.objects.values('dep_id').annotate(s=Avg('salary'))
#查询每个部门的id以及对对应的员工的最大年龄
ret = models.Emp.objects.values('dep_id').annotate(a=Max('age'))
#Emp表示表,values中的字段表示按照哪个字段group by,annotate里面是显示分组统计的是什么
#连表:
# 查询每个部门的名称以及对应的员工个数和员工最大年龄
ret = models.Emp.objects.values('dep__name').annotate(a=Count('id'),b=Max('age')) #注意,正向与反向的结果可能不同,如果反向查的时候,有的部门还没有员工,那么他的数据也会被统计出来,只不过值为0,但是正向查的话只能统计出来有员工的部门的相关数据,因为通过你是员工找部门,而不是通过部门找员工,结果集里面的数据个数不同,但是你想要的统计结果是一样的
#<QuerySet [{'a': 1, 'dep__name': '销售部', 'b': 12}, {'a': 3, 'dep__name': '人事部', 'b': 22}]>
#使用双下划线进行连表,然后按照部门名称进行分组,然后统计员工个数和最大年龄,最后结果里面显示的是部门名称、个数、最大年龄。
#注意:如果values里面有多个字段的情况:ret = models.Emp.objects.values('dep__name','age').annotate(a=Count('id'),b=Max('age')) #是按照values里面的两个字段进行分组,两个字段同时相同才算是一组,看下面的sql语句''' SELECT `app01_dep`.`name`, `app01_emp`.`age`, COUNT(`app01_emp`.`id`) AS `a`, MAX(`app01_emp`.`age`) AS `b` FROM `app01_emp` INNER JOIN `app01_dep` ON (`app01_emp`.`dep_id` = `app01_dep`.`id`) GROUP BY `app01_dep`.`name`, `app01_emp`.`age`;'''
下面是书籍表和出版社表的一个连表分组的sql语句写法:
查询练习
(1) 练习:统计每一个出版社的最便宜的书
publishList=Publish.objects.annotate(MinPrice=Min("book__price")) #如果没有使用objects后面values或者values_list,得到的结果是queryset类型,里面是Publish的model对象,并且是对所有记
录进行的统计,统计的Minprice也成了这些model对象里面的一个属性,这种连表分组统计的写法最常用,思路也比较清晰
for publish_obj in publishList:
print(publish_obj.name,publish_obj.MinPrice)
annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:
queryResult= Publish.objects
.annotate(MinPrice=Min("book__price"))
.values_list("name","MinPrice")
print(queryResult)
'''
SELECT "app01_publish"."name", MIN("app01_book"."price") AS "MinPrice" FROM "app01_publish"
LEFT JOIN "app01_book" ON ("app01_publish"."nid" = "app01_book"."publish_id")
GROUP BY "app01_publish"."nid", "app01_publish"."name", "app01_publish"."city", "app01_publish"."email"
'''
(2) 练习:统计每一本书的作者个数
ret=Book.objects.annotate(authorsNum=Count('authors__name'))
ret=models.Book.objects.annotate(authorsNum=Count('authors__name')).values('title','authorsNum') #注意写法,values里面写的个数的别名ret=models.Book.objects.annotate(a=Count('author__name')).filter(a__gt=2).values('title','a') #还有这种写法,看看你能不能明白这是在做什么
(3) 统计每一本以py开头的书籍的作者个数:
queryResult=Book.objects
.filter(title__startswith="Py")
.annotate(num_authors=Count('authors')) #连接第三张表再连接author表,where title regexp '^Py' 然后按照连表后的大表中的book表的title字段进行分组,并且统计对应作者的个数
(4) 统计不止一个作者的图书:
queryResult=Book.objects
.annotate(num_authors=Count('authors'))
.filter(num_authors__gt=1) #filter也是也可以是querset来调用
(5) 根据一本图书作者数量的多少对查询集 QuerySet
进行排序:
Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
(6) 查询各个作者出的书的总价格:
# 按author表的所有字段 group by
queryResult=Author.objects .annotate(SumPrice=Sum("book__price")) .values_list("name",&qu