聚合查询与分组查询
聚合查询:
aggregate(*args, **kwargs)
#1.聚合 aggregate:返回值是一个字典 from django.db.models import Avg,Max,Min,Count #问题:查询所有书籍的平均价格,最高价格,最低价格 ret = Book.objects.all().aggregate(avg_price=Avg('price'),max_price = Max('price'),min_price=Min('price')) print(ret)
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
1.单表分组查询
单表查询
\
查询每个部门的的平均薪资
#************************************************聚合与分组查询***************************************************** #----------------------聚合 aggregate:返回值是一个字典-------------------------- from django.db.models import Avg,Max,Min,Count # --------------------分组 annotate 返回的是一个queryset----------------------------- #查询每个部门的平均薪资 #sql:SELECT dep AS 部门, AVG(salary) AS 平均薪资 FROM app01_emp GROUP BY dep; #ORM ret=emp1.objects.values('dep').annotate(平均薪资=Avg('salary')) print(ret)
单表分组查询语法总结:
表单模型.objects.values("group by 分组字段").annotate(聚合函数('聚合字段'))
'''单表分组查询总结: 表单模型.objects.values("group by 分组字段").annotate(聚合函数('聚合字段')) 补充知识: emp1.objects.all() === select * from emp1 emp1.objects.all().values('dep') === select emp1.dep from emp1 ===emp1.objects.values('dep') emp1.objects.all().annotate(Avg('salary')) 分组时包含了主键,这样就是去了分组的意义 分组查询的意义在于把一个字段下多个值进行分组.如果使用了主键进行分组,相当于使用select * form emp1 没有意义 '''
2.跨表分组查询
跨表查询
#1.查询每个出版社出版的书籍数量以及出版社名称 # SQL:SELECT app01_publish.name AS 出版社,COUNT(nid) AS 书籍数量 FROM app01_book INNER JOIN app01_publish ON app01_book.publish_id = app01_publish.nid GROUP BY (publish_id); #ORM: 正向查询 ret=Book.objects.values('publish__name').annotate(书籍数量=Count('publish__name')) print(ret) # <QuerySet [{'publish__name': '人民出版社', '书籍数量': 3}, {'publish__name': '电子工业出版社', '书籍数量': 1}, {'publish__name': '清华大学出版社', '书籍数量': 1}]> ''' 这里需要弄清楚sql语句的执行顺序 注意:第一个publish__name是按照正向查询时book表下的字段publish中的name.第二个publish__name是连表时候按照表名小写加上__字段 ''' # 反向查询: ret = Publish.objects.values('nid').annotate(书籍数量=Count('book__name')).values('name','书籍数量') print(ret) # # <QuerySet [{'name': '人民出版社', '书籍数量': 3}, {'name': '电子工业出版社', '书籍数量': 1}, {'name': '清华大学出版社', '书籍数量': 1}]> #
#2.查询每个作者的名字以及出版过的书籍的最高价格 # SQL:SELECT app01_author.`name`, MAX(price) FROM app01_author INNER JOIN app01_book_author ON app01_author.id = app01_book_author.author_id # # INNER JOIN app01_book ON app01_book.bid = book_id # # GROUP BY author_id ret = Author.objects.values('pk').annotate(price_max=Max('book__price')).values('name','price_max') print(ret) ''' 跨表查询总结: 每个后表模型.objects.values('基表主键 pk').annotate(聚合函数(关联表__查询字段)).values('表模型所有字段','聚合函数字段')
例如:查询每个作者的名字以及出版过的书籍的最高价格 这里每个后面的字符,就是基表,这个基表就是作者表 '''
总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。
查询练习
1.统计每一个出版社的最便宜的书
'''SQL: SELECT app01_publish.`name` AS Publish_name,app01_book.`name` AS Book_name,MIN(price) AS Min_price FROM app01_publish INNER JOIN app01_book ON app01_publish.nid = app01_book.publish_id GROUP BY app01_publish.nid '''
ORM语句:
ret = Publish.objects.values('pk').annotate(Min_price=Min('book__price')).values_list('name','Min_price') print(ret)
2.统计每本书的作者数量
''' SELECT app01_book.`name`,COUNT(author_id) FROM app01_book INNER JOIN app01_book_author ON app01_book.bid = app01_book_author.book_id GROUP BY app01_book.bid ''' # ORM: ret = Book.objects.values('pk').annotate(c=Count('author__id')).values('name','c') print(ret)
3.