聚合

aggregate(*args, **kwargs)

  1. # 计算所有图书的平均价格
  2. from django.db.models import Avg
  3. Book.objects.all().aggregate(Avg('price'))
  4. #{'price__avg': 34.35}

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

  1. Book.objects.aggregate(average_price=Avg('price'))
  2. #{'average_price': 34.35}

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

  1. from django.db.models import Avg, Max, Min
  2. Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
  3. #{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
  1. # 查询所有书籍的平均价格
  2. from django.db.models import Avg,Count,Max,Min
  3. ret=Book.objects.all().aggregate(Avg('price'))
  4. # {'price__avg': 202.896}
  5. # 可以改名字
  6. ret=Book.objects.all().aggregate(avg_price=Avg('price'))
  7. # 统计平均价格和最大价格
  8. ret=Book.objects.all().aggregate(avg_price=Avg('price'),max_price=Max('price'))
  9. # 统计最小价格
  10. ret = Book.objects.all().aggregate(avg_price=Avg('price'), min_price=Min('price'))
  11. # 统计个数和平均价格
  12. ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('price'))
  13. ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('nid'))
  14. print(ret)

案例

  1.  
  1.  

分组

annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。 

查找练习

练习:统计每一本书作者个数

  1. from django.db.models import Avg, Max, Sum, Min, Max, Count
  2. book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
  3. for book in book_list:
  4. print(book.name)
  5. print(book.author_num)
  6. book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values('name','author_num')
  7. print(book_list)

练习:统计每一个出版社的最便宜的书

  1. publishList=Publish.objects.annotate(MinPrice=Min("book__price"))
  2. for publish_obj in publishList:
  3. print(publish_obj.name,publish_obj.MinPrice)

annotate的返回值是querySet,如果不想遍历对象,可以用上valuelist:

  1. queryResult= Publish.objects.annotate(MinPrice=Min("book__price")).values_list("name","MinPrice")
  2. print(queryResult)

练习:统计每一本以py开头的书籍的作者个数:

  1. queryResult=Book.objects.filter(title__startswith="Py").annotate(num_authors=Count('authors'))

练习:统计不止一个作者的图书:(作者数量大于一)

  1. ret=models.Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
  2. print(ret)

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

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

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

  1. ret=models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")
  2. print(ret)

练习:查询每个出版社的名称和书籍个数

  1. ret=models.Publish.objects.all().annotate(c=Count('book__name')).values('name','c')
  2. print(ret)
  1. # ————————————单表下的分组查询
  2. '''
  3. 查询每一个部门名称以及对应的员工数
  4. emp:
  5. id name age salary dep
  6. 1 alex 12 2000 销售部
  7. 2 egon 22 3000 人事部
  8. 3 wen 22 5000 人事部
  9. '''
  10. # select count(id) from emp group by dep
  11. # 示例一:查询每一个部门的名称,以及平均薪水
  12. # select dep,Avg(salary) from app01_emp group by dep
  13. from django.db.models import Avg, Count, Max, Min
  14. ret=Emp.objects.values('dep').annotate(Avg('salary'))
  15. # 重新命名
  16. ret=Emp.objects.values('dep').annotate(avg_salary=Avg('salary'))
  17. print(ret)
  18. # ---*******单表分组查询ORM总结:表名.objects.values('group by 的字段').annotate(聚合函数('统计的字段'))
  19. # 示例2 查询每个省份对应的员工数
  20. ret=Emp.objects.values('province').annotate(Count('id'))
  21. ret=Emp.objects.values('province').annotate(c=Count('id'))
  22. print(ret)
  23. # 补充知识点:
  24. ret=Emp.objects.all()
  25. # select * from emp
  26. ret=Emp.objects.values('name')
  27. # select name from emp
  28. # ****单表下,按照id进行分组是没有任何意义的
  29. ret=Emp.objects.all().annotate(Avg('salary'))
  30. print(ret)
  31. # ******多表分组查询
  32. # 查询每一个出版社出版的书籍个数
  33. ret=Book.objects.values('publish_id').annotate(Count('nid'))
  34. print(ret)
  35. # 查询每个出版社的名称以及出版社书的个数(先join在跨表分组)
  36. # 正向
  37. ret=Publish.objects.values('name').annotate(Count('book__name'))
  38. ret=Publish.objects.values('nid').annotate(c=Count('book__name')).values('name','c')
  39. print(ret)
  40. # 反向
  41. ret=Book.objects.values('publish__name').annotate(Count('name'))
  42. ret=Book.objects.values('publish__name').annotate(c=Count('name')).values('publish__name','c')
  43. print(ret)
  44. # 查询每个作者的名字,以及出版过书籍的最高价格
  45. ret=Author.objects.values('pk').annotate(c=Max('book__price')).values('name','c')
  46. print(ret)
  47. # 跨表查询的模型:每一个后表模型.objects.value('pk').annotate(聚合函数('关联表__统计字段')).values()
  48.  
  49. # 查询每一个书籍的名称,以及对应的作者个数
  50. ret=Book.objects.values('pk').annotate(c=Count('authors__name')).values('name','c')
  51. print(ret)
  52. # 统计不止一个作者的图书
  53. ret=Book.objects.values('pk').annotate(c=Count('authors__name')).filter(c__gt=1).values('name','c')
  54. print(ret)

F查询与Q查询

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

  1. # 查询评论数大于收藏数的书籍
  2. from django.db.models import F
  3. Book.objects.filter(commnetNum__lt=F('keepNum'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

  1. # 查询评论数大于收藏数2倍的书籍
  2. Book.objects.filter(commnetNum__lt=F('keepNum')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元:

  1. Book.objects.all().update(price=F("price")+30) 

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象

  1. from django.db.models import Q
  2. Q(title__startswith='Py')

Q 对象可以使用& 和| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。

  1. bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))

等同于下面的SQL WHERE 子句:

  1. WHERE name ="yuan" OR name ="egon"

你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:

  1. bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017), title__icontains="python")
  1. # 查询评论数大于阅读数的书籍
  2. from django.db.models import F,Q
  3. # select * from book where commit_num>read_num;
  4. # 这样肯定是不行的
  5. # Book.objects.filter(commit_num__gt=read_num)
  6. ret=Book.objects.filter(commit_num__gt=F('reat_num'))
  7. print(ret)
  8. # 把所有书籍的价格加10
  9. Book.objects.all().update(price=F('price')+10)
  10. # ----Q函数,描述一个与,或,非的关系
  11. # 查询名字叫红楼梦或者价格大于100的书
  12. ret=Book.objects.filter(Q(name='红楼梦')|Q(price__gt=100))
  13. print(ret)
  14. # 查询名字叫红楼梦和价格大于100的书
  15. ret = Book.objects.filter(Q(name='红楼梦') & Q(price__gt=100))
  16. print(ret)
  17. # # 等同于
  18. ret2=Book.objects.filter(name='红楼梦',price__gt=100)
  19. print(ret2)
  20. # 也可以Q套Q
  21. # 查询名字叫红楼梦和价格大于100 或者 nid大于2
  22. ret=Book.objects.filter((Q(name='红楼梦') & Q(price__gt=100))|Q(nid__gt=2))
  23. print(ret)
  24. # ----非
  25. ret=Book.objects.filter(~Q(name='红楼梦'))
  26. print(ret)
  27. # Q和键值对联合使用,但是键值对必须放在Q的后面(描述的是一个且的关系)
  28. # 查询名字不是红楼梦,并且价格大于100的书
  29. ret=Book.objects.filter(~Q(name='红楼梦'),price__gt=100)
  30. print(ret)

Django分表操作、聚合及FQ方法的更多相关文章

  1. Django之ORM操作(聚合 分组、F Q)

    Django之ORM操作(聚合 分组.F Q) 聚合 aggregate()是QuerySet的一个终止子句,也就是说,他返回一个包含一些键值对的字典,在它的后面不可以再进行点(.)操作.   键的名 ...

  2. mysql分表操作

    一般分表操作有垂直拆分和水平拆分.顾名思义. 1.  垂直拆分是指,这个表的列,即字段,要拆分成两个或多个表. 这个应用场景比如:这个表字段,几个都是int.datetime等,有那么一个是text类 ...

  3. Mycat本地模式的自增长分表操作

    Mycat对表t_rc_rule_monitor做分表操作 在mysql上执行(没有t_rc_rule_monitor) DROP TABLE IF EXISTS t_rc_rule_monitor; ...

  4. zabbix 数据库分表操作

    近期zabbix数据库占用的io高,在页面查看图形很慢,而且数据表已经很大,将采用把数据库的数据目录移到新的磁盘,将几个大表进行分表操作 一.数据迁移: 1.数据同步到新的磁盘上,先停止mysql(不 ...

  5. mysql分表场景分析与简单分表操作

    为什么要分表 首先要知道什么情况下,才需要分表个人觉得单表记录条数达到百万到千万级别时就要使用分表了,分表的目的就在于此,减小数据库的负担,缩短查询时间. 表分割有两种方式: 1水平分割:根据一列或多 ...

  6. MyBatis实现Mysql数据库分库分表操作和总结

    前言 作为一个数据库,作为数据库中的一张表,随着用户的增多随着时间的推移,总有一天,数据量会大到一个难以处理的地步.这时仅仅一张表的数据就已经超过了千万,无论是查询还是修改,对于它的操作都会很耗时,这 ...

  7. Django单表操作

    一.数据库相关设置 配置ORM的loggers日志: # 配置ORM的loggers日志 LOGGING = { 'version': 1, 'disable_existing_loggers': F ...

  8. Django 多表查询 聚合查询 分组查询 F查询 Q查询

    # -------------------------------------------------------------------------------------------------- ...

  9. Django多表操作

    多表创建 创建模型 下面通过一个简单的图书管理系统,来阐述多表的创建和查询操作 在视图函数里里定义如下代码 from django.db import models class Book(models ...

随机推荐

  1. centos7下python2环境安装pip2、kazoo、bottle、beaker

    摘自:https://mp.weixin.qq.com/s?src=11&timestamp=1576355125&ver=2034&signature=mNp2na6VjFz ...

  2. nodejs 读取目前下所有文件

    var fs = require('fs'); var join = require('path').join; function getJsonFiles(jsonPath) { let jsonF ...

  3. [简短问答]C-Lodop中一些测试用的地址

    测试访问:访问http://localhost:8000欢迎页面试试进入欢迎页面http://localhost:8000,点欢迎页面的预览试试 查看下c-lodop启动界面,在设置里查看下当前启动的 ...

  4. [LeetCode] 126. Word Ladder II 词语阶梯 II

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  5. windows下Java调用可执行文件

    缘起: 由于没有找到java转换文件的接口,因此使用java调用exe文件进行文件转换 public void convertFile(){ Runtime rn = Runtime.getRunti ...

  6. 在ObjectARX中创建OPM项目的时候出现 MIDL1012: argument illegal for switch / header错误的解决方式

    修改为 这样新建的带有MIDL项目就不会提示错误这个错误了. 如果你已经建立好项目,可以尝试修改MIDL的配置,头文件可能是.h没有文件名,所以出现MIDL1012错误,修改为项目名称的.h即可,保持 ...

  7. LeetCode 22. 括号生成(Generate Parentheses)

    22. 括号生成 22. Generate Parentheses 题目描述 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结 ...

  8. Spark源码(1) Spark配置

    写熟悉的第一句代码 val conf = new SparkConf().setAppName("WordCount")点击SparkConf() ,发现 private val ...

  9. Json 文件读写以及和IniFile 转换

    JSON 文件是越来越受欢迎了,以前程序配置文件用Ini,Ini 简练,简单.方便,但是也有不少缺点,比如,没有 JSON 直观,无法存储复杂点的数据类型. 于是乎,我封装了一个TJsonFile 的 ...

  10. Huawei重新开启隐藏桌面功能

    在HUAWEI的EMUI系统7.0的时候我们都能发现桌面上靠手指操作的隐藏桌面的功能,像这样: 但是在之后的EMUI8.0.9.0,之后就没有办法用了.后来问了官方,这个功能确实是被去掉了.个人也很不 ...