zoukankan      html  css  js  c++  java
  • Django ORM聚合查询,分组查询

    聚合查询方法名aggregate(),返回的是一个字典,不是queryset,而annotate()返回的是一个queryset,

    2个方法区别是aggregate是对一组值进行计算,而annotate更多的是一组值进行group by后再进行计算.

    聚合方法需要搭配具体计算的方法一起使用,需要导入avg max min count from django.db.models import Count,Avg,Max,Min

    计算书本的平均价格,返回值的key值为 `字段__avg`,
    

    book = models.Book.objects.all().aggregate(Avg("price")) #{'price__avg': Decimal('31.593333')}

    也可以自定义key值

    book2 = models.Book.objects.all().aggregate(avg_price =Avg("price")) #{'avg_price': Decimal('31.593333')}

    分组查询

    ORM中,book.Object.all() 等于sql语句的select * from book,而book.Object.all().values("publish")等于sql语句的select publish from book,
    ORM中的values有2种意思,一个是只提取publish字段显示,如果Book.objects.values("publish_id").annotate 后面跟了聚合函数,也会按照该字段进行分组.
    所以Book.objects.all().annotate 是一句没有意义的聚合命令,因为all()里面包含了id,每条记录都是不同的,因此无法产生按照特定字段进行聚合.

      比如emp表,需要统计各个部门的人数
        emp:
        id  name    age dep
        1   alex        18  销售部
        2   blex        38  销售部
        3   clex        28  市场部
        4   dlex        48  客服部
        
        sql语句
        select Count(id) from emp group by dep; 通过对dep字段分组,再对每组的id个数进行统计
        单表中的分组查询
        orm中分组是用annotate(),返回值是一个query set 
        使用语法是前面先用value("dep").annotate(Avg("age"))
        value("dep") 等于明确按dep分组,语法等同于group by dep
        例子:
        avg_age = models.Book.objects.values("publish_id").annotate(zidingyi =Avg("price"))  #key值和aggregate一样可以自定义
        # QuerySet[{'publish_id': 1, 'zidingyi': Decimal('38.275000')}, {'publish_id': 2, 'zidingyi': Decimal('18.230000')}]
    
    

    跨表之组合查询

    # 跨表分组查询模板
    # 每一个后表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)).values("表模型中的所有字段或者需要统计的字段")
    # 每一个后表模型.objects.annotate(聚合函数(关联表__统计字段)).values("表模型中的所有字段或者需要统计的字段")
    # 每一个后表模型.objects.all().annotate(聚合函数(关联表__统计字段)).values("表模型中的所有字段或者需要统计的字段")
    上面第二个和第三个效果等同,因为values("pk")只是选择了pk这个字段,同时带有按这个字段group by的效果
    但是我们用all()或者省略不写,ORM的语法意思是按照这个对象的所有字段进行group by的意思.
    

    例1:查询出版社的名称以及出版的书本个数
    sql语句示例

    select my_book_publish.name,Count(my_book_book.title) from my_book_book inner join my_book_publish on my_book_book.publish_id = my_book_publish.pid group by my_book_publish.pid;

    ORM语句示例
    以publish为基表有三种写法,推荐用第二种,因为pid是唯一的,而有时候如果name会有重复,比如name为人名的时候

        pub = models.Publish.objects.values("pid").annotate(c =Count("book__title"))
        #< QuerySet[{'pid': 1, 'c': 3}, {'pid': 2, 'c': 2}, {'pid': 3, 'c': 1}] >
        # group by pid,然后annotate通过反向查询 表名__字段 对该字段进行聚合计算,但是结果只显示出版社的pid
        pub = models.Publish.objects.values("pid").annotate(c=Count("book__title")).values("name","c")
        #<QuerySet [{'name': '南京出版社', 'c': 3}, {'name': '北京出版社', 'c': 2}, {'name': '浙江出版社', 'c': 1}]>
        # 因为前面语句已经把2张表拼成了一张表,里面除了出版社和book的字段,c 这个计算结果字段也会包含在内,所以我们要显示出版社name和c可以再加个values进行展示
        pub = models.Publish.objects.values("name").annotate(c=Count("book__title"))
        # group by name,然后annotate通过反向查询 表名__字段 对该字段进行聚合计算
        # <QuerySet [{'name': '南京出版社', 'c': 3}, {'name': '北京出版社', 'c': 2}, {'name': '浙江出版社', 'c': 1}]>
    

    例2:查询每一个作者的名字以及他们出版过书籍的最高价格

        sql语句:  select name,MAX(price) from my_book_book inner join my_book_book_author on my_book_book.id = my_book_book_author.book_id inner join my_book_author on my_book_book_author.author_id = my_book_author.aid group by aid
        
        pub = models.Author.objects.values("pk").annotate(c = Max("book__price")).values("name","c")
        #models.Author.objects.values("pk").annotate(c = Max("book__price"))等于是把author ,book author_book三张表join成了一张,后面可以选择要显示的内容
        #<QuerySet [{'name': 'blex', 'c': Decimal('28.23')}, {'name': 'clex', 'c': None}, {'name': 'alex', 'c': Decimal('28.23')}]>
    
    

    例3: 查询每一个书籍的名称和对应的作者个数

      sql语句:
        #select title,count(aid) as "作者个数" from my_book_book inner join my_book_book_author  on my_book_book.id = book_id inner join my_book_author on my_book_book_author.author_id = my_book_author.aid group by book_id;
    
        pub = models.Book.objects.values("pk").annotate(c = Count("author__aid")).values("title","c")
        #Count("author__aid")这里的author是字段不是表名,因为book下本来就有author字段,正向查找按字段
        #<QuerySet [{'title': 'python', 'c': 2}, {'title': 'java', 'c': 2}, {'title': 'c++', 'c': 0}, {'title': 'go', 'c': 0}, {'title': 'c#', 'c': 0}, {'title': 'php', 'c': 0}]>
        #我们也可以通过book查其他表下的字段,语法: 字段(表名)__字段
        pub=models.Book.objects.values("pk").annotate(c=Count("author__name")).filter(c__gt=1).values("title","publish__name")
    
  • 相关阅读:
    Linq to LLBL Gen Pro LLBL Gen的Linq程序设计
    应用反射技术为Infragistics Solution设计例子程序 代码简洁而且学习的效率高
    ASP.NET Web开发框架之零 项目介绍
    .NET 应用程序界面开发经验总结 设计良好的程序的表现之一就是细节做的还可以
    ORM Querier 基于TransactSQL解析的代码生成利器 帮助开发人员高效快速生成需要的ORM代码
    Visual Studio 2010 开发与调试IronPython脚本 为你的ERP/MIS 应用程序添加脚本功能
    ORM + .NET Remoting 完整例子程序 虽然现在都流行WCF,也没有必要抛弃已经掌握的.NET Remoting
    总结一下ERP .NET程序员必须掌握的.NET技术,掌握了这些技术工作起来才得心应手
    LLBL Gen 元数据编程 LLBL Gen Metadata Programming
    iPhone开发笔记[14/50]:没有开发者证书,先用模拟器也要开发
  • 原文地址:https://www.cnblogs.com/Young-shi/p/15174328.html
Copyright © 2011-2022 走看看