基于双下划线的双表查询

分组与聚合函数

基于双下划线的双表查询

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. postman传递对象到spring controller的方式

    1.spring Controller @RestController @RequestMapping(value = "/basic/task") public class Ta ...

  2. 微信支付的JAVA SDK存在漏洞,可导致商家服务器被入侵(绕过支付)XML外部实体注入防护

    XML外部实体注入 例: InputStream is = Test01.class.getClassLoader().getResourceAsStream("evil.xml" ...

  3. Django 学习笔记(三) --- HTML 模版加载 css、js、img 静态文件

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  4. HashMap源码解读(JDK1.7)

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...

  5. laravel 制作购物车流程

    ① 购入车数据如何存放? 创建数据表 用户ID 购物时间 缺点: 对服务器有压力. 方案: 定时删除 coolie中: 缺点: 数据不能跨客户端 优点:不会对服务器产生压力 放东西和数量 显示购物车 ...

  6. Layui 获取 radio的值

    var OutInvoiceType = $('#OutInvoiceType input[checked]').val();   就可以获取到了.

  7. 【Spring】26、利用Spring的AbstractRoutingDataSource解决多数据源,读写分离问题

    多数据源问题很常见,例如读写分离数据库配置. 1.首先配置多个datasource <bean id="dataSource" class="org.apache. ...

  8. WCF Service 转换为Web Service 中字段属性

    1.新建WCF服务,服务中包含对象 2.部署WCF服务,并将其转换为应用程序 3.通过添加服务引用,使用WCF服务 4.调用对应的对象时需要对应的值设置为True. 参考:https://cloud. ...

  9. Spring基于纯注解方式的使用

    经过上篇xml与注解混合方式,对注解有了简单额了解,上篇的配置方式极大地简化了xml中配置,但仍有部分配置在xml中进行,接下来我们就通过注解的方式将xml中的配置用注解的方式实现,并最终去掉xml配 ...

  10. Vue.js MVVM及数据绑定原理

    什么是数据驱动 数据驱动是vuejs最大的特点.在vuejs中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom. 比如说我们点击一个button,需要元 ...