zoukankan      html  css  js  c++  java
  • Django之ORM查询进阶

    基于双下划线的双表查询

    分组与聚合函数

    基于双下划线的双表查询

    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="151")
                .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="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"))#都是通过自己里面的字段跳转到别的字段
    
        #聚合函数
        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}
    View Code

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

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

    如果你希望生成不止一个聚合,你可以向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对象
    View Code

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

    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

     
     
  • 相关阅读:
    maven笔记
    enum笔记
    mysql笔记
    git笔记
    spark笔记
    使用GitHub进行团队合作
    深度学习网站
    顶级论文索引网站
    研究生-数学建模集
    算法练习网站
  • 原文地址:https://www.cnblogs.com/1a2a/p/7757956.html
Copyright © 2011-2022 走看看