基于双下划线的双表查询

分组与聚合函数

基于双下划线的双表查询

Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止。

# 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)

    # 正向查询 按字段:publish

    queryResult=Book.objects
            .filter(publish__name="人民出版社")
            .values_list("title","price") # 反向查询 按表名:book queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("book__title","book__price") # 练习2: 查询egon出过的所有书籍的名字(多对多) # 正向查询 按字段:authors:
queryResult=Book.objects
            .filter(authors__name="yuan")
            .values_list("title") # 反向查询 按表名:book
queryResult=Author.objects
              .filter(name="yuan")
              .values_list("book__title","book__price") # 练习3: 查询人民出版社出版过的所有书籍的名字以及作者的姓名 # 正向查询
queryResult=Book.objects
            .filter(publish__name="人民出版社")
            .values_list("title","authors__name")
# 反向查询
queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("book__title","book__authors__age","book__authors__name") # 练习4: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称 queryResult=Book.objects
            .filter(authors__authorDetail__telephone__regex="")
            .values_list("title","publish__name")

代码

 
#手机号以456开头的作者出版过的所有书籍的名字以及出版社的名字
#方法1
authorobj=models.AuthorDetail.objects.filter(telph__startswith="456").first()
# print(authorobj.authordetail.book_set.all().values("title","publish__name"))
#方法2
# print(models.Book.objects.filter(authorlist__authordetail__telph__startswith="456").values("title","publish__name"))#都是通过自己里面的字段跳转到别的字段


注意:

反向查询时,如果定义了related_name ,则用related_name替换表名,例如: publish = ForeignKey(Blog, related_name='bookList'):

# 练习1:  查询人民出版社出版过的所有书籍的名字与价格(一对多)
 
    # 反向查询 不再按表名:book,而是related_name:bookList
 
    queryResult=Publish.objects
              .filter(name="人民出版社")
              .values_list("bookList__title","bookList__price")

代码

注意:    双下划线的跨表查询  不用__set了

#双下划线的跨表查询
# linux这本书的出版社的地址
# ret=models.Book.objects.filter(title="linux").values("publish__addr")
# print(ret)
# ret=models.Publish.objects.filter(book__title="linux").values("addr")
# print(ret)
#查询机械出版社出版过的所有书籍的名字与价格
# ret=models.Publish.objects.filter(name="机械出版社").values("book__title","book__price")
# print(ret)
# models.Book.objects.filter(publish__name="机械出版社").values("title","price")
# print(ret)
#查询frank出过所有书籍的名字
# ret=models.Author.objects.filter(name="frank").values("book__title","book__price")
# print(ret)
# ret1=models.Book.objects.filter(authorlist__name="frank").values("title","price")
# print(ret1)
#手机号以456开头的作者出版过的所有书籍的名字以及出版社的名字
#方法1
authorobj=models.AuthorDetail.objects.filter(telph__startswith="").first()
# print(authorobj.authordetail.book_set.all().values("title","publish__name"))
#方法2
# print(models.Book.objects.filter(authorlist__authordetail__telph__startswith="456").values("title","publish__name"))#都是通过自己里面的字段跳转到别的字段 #聚合函数
from django.db.models import Avg,Sum,Count,Max,Min
# ret =models.Book.objects.all().aggregate(priceSum=Sum("price"))#结果是字典可以替换名字
# ret = models.Book.objects.all().aggregate(priceAVG=Avg("price"),priceSum=Sum("price"))
# print(ret)
# 分组函数 annote函数
#查询每一本书的作者个数
# ret= models.Book.objects.all().annotate(c=Count("authorlist__name"))
# print(ret)#Queryset对象 #每一个出版社出版过的最便宜的书:
cc=models.Publish.objects.all().annotate(s=Min("book__price"))#如果是跨表查询就用表明__加id
for i in cc:
print(i.s)

聚合查询与分组查询

聚合:aggregate(*args, **kwargs)

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

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

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}

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

>>> from django.db.models import Avg, Max, Min
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}#Decimal数据格式

分组:annotate()

QuerySet中每一个对象都生成一个独立的汇总值。

(1) 练习:统计每一本书的作者个数

  #查询每一本书的作者个数
# ret= models.Book.objects.all().annotate(c=Count("authorlist__name"))
# print(ret)#Queryset对象

(2)每一个出版社出版过的最便宜的书:
cc=models.Publish.objects.all().annotate(s=Min("book__price"))#如果是跨表查询就用表明__加id
for i in cc:
print(i.s)

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

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

方式2:

queryResult=Book.objects.values("publish__name").annotate(MinPrice=Min('price'))

注意:values内的字段即group by的字段

(3) 统计每一本以py开头的书籍的作者个数:

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

(4) 统计不止一个作者的图书:

queryResult=Book.objects
          .annotate(num_authors=Count('authors'))
          .filter(num_authors__gt=1)

(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","SumPrice")
print(queryResult) #按authors__name group by
queryResult2=Book.objects.values("authors__name")
              .annotate(SumPrice=Sum("price"))
              .values_list("authors__name","SumPrice")
print(queryResult2)

注意:很多代码没有加models

 
 

Django之ORM查询进阶的更多相关文章

  1. Django之ORM查询复习与cookie

    ORM查询总结: models.Book.objects.filter(**kwargs): querySet [obj1,obj2] models.Book.objects.filter(**kwa ...

  2. Django之ORM查询

    ORM 映射关系: 表名 <-------> 类名 字段 <-------> 属性 表记录 <------->类实例对象图书管理系统的增删改查:代码如下:views ...

  3. Django 的 orm 查询

    一.模型关系表 1. 一对一 Author-AuthorDetail 关联字段可以在任意表下,但必须唯一约束.(unique约束) ad_id(unique约束) ad = models.oneToO ...

  4. [django]django的orm查询

    实体 实体 出版社 category 作者 tag 书 文章 先学习一下基础的增删查改 django orm增删改查: https://www.cnblogs.com/iiiiiher/article ...

  5. django优化--ORM查询

    ORM提供了两个方法用来优化查询效率 1. select_related 有两张表:表结构如下: class Scheme(models.Model): """ 套餐类 ...

  6. Django之ORM查询操作详解

    浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Python脚本中调用Django环境 其他操 ...

  7. 【python】-- Django ORM(进阶)

    Django ORM(进阶) 上一篇博文简述了Django ORM的单表操作,在本篇博文中主要简述Django ORM的连表操作. 一.一对多:models.ForeignKey() 应用场景:当一张 ...

  8. 第五章、Django之多表查询进阶与事务

    目录 第五章.Django之多表查询 一.聚合查询 二.分组查询 三.F与Q查询 四.查询优化 五.Django开启事务 六.自定义char字段 七.ORM常用字段 第五章.Django之多表查询 一 ...

  9. Django 源码小剖: Django ORM 查询管理器

    ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从 ...

随机推荐

  1. jqgrid表头上面再加一行---二级表头

    实现效果如图,代码如下: $( "#table_list_1" ).jqGrid( 'setGroupHeaders' , { useColSpanStyle : true , / ...

  2. Java基础之基本数据类型

    前言:Java内功心法之基本数据类型,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 变量就是申请内存来存储值.也就是说,当创建变量的时候,需 ...

  3. python元祖操作和内置方法

    1 元祖:元祖可以理解为一个不可变的列表 2 用途:用于存放多个值,当存放的多个值只有读的需求而没有改的需求时用元祖最合适 3 定义:在()内用逗号分隔开多个任意类型的值.注意:当只有一个元素的时候, ...

  4. 前端迷思与React.js

    前端迷思与React.js 前端技术这几年蓬勃发展, 这是当时某几个项目需要做前端技术选型时, 相关资料整理, 部分评论引用自社区. 开始吧: 目前, Web 开发技术框架选型为两种的占 80% .这 ...

  5. 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  6. (转)Linux企业运维人员最常用150个命令汇总

    目录 线上查询及帮助命令(2个) 文件和目录操作命令(18个) 查看文件及内容处理命令(21个) 文件压缩及解压缩命令(4个) 信息显示命令(11个) 搜索文件命令(4个) 用户管理命令(10个) 基 ...

  7. 2.C++中的bool类型,三目运算符,引用

    本章主要内容: 1)bool类型 2)三目运算符 3)引用 1.布尔型bool 在C++中,bool类型只有true(非0)和flase(0)两个值,且bool类型只占用了一个字节. 例如: #inc ...

  8. APP接口调用流程

  9. 将表格导出为excel

    <table id="tableExcel" border="1"> <tr> <th>零</th> <t ...

  10. js 复制文本到粘贴板

    //html 在iOS Safari中,剪贴板API有一些限制(实际上是安全措施):   于安全原因,iOS Safari只允许容器中的document.execCommand('copy')文本co ...