• day057聚合分组查询(接多表查询)


    本节内容:接多表操作

    1、聚合查询与分组查询
    2、F查询与Q查询
    

    一、聚合查询与分组查询

    1、聚合

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

    fe1:计算所有图书的平均价格

    from django.db.models import Avg
    Book.objects.all().aggregate(Avg('price'))
        # {'price__avg': 34.35}
    
    Python

    fe2:查询学生总人数

    models.Student.objects.all().aggregate(c=Count('*'))
    
    Python

    1、如果你希望生成不止一个聚合,你可以向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')}
    
    Python

    2、分组查询

    1、单表分组查询

    #查询每一个部门名称以及对应的员工数
    
    sql:
        select dep,Count(*) from emp group by dep;
        select dep,AVG(salary) from emp group by dep;
    
    orm:
        queryset=models.Emp.objects.values("dep").annotate(c=Count("*"))
    '''
    from django.db.models import Avg,Count,Max,Min
    
    # 查询每一个部门的人数
    #  queryset=models.Emp.objects.values("dep").annotate(c=Count("*"))
    #  print(queryset)  # <QuerySet [{'dep': '销售部', 'c': 1}, {'dep': '人事部', 'c': 2}]>
    #
    # # 查询每一个省份的平均薪水
    #  queryset=models.Emp.objects.values("province").annotate(avg_salary=Avg("salary"))
    #  print(queryset) # <QuerySet [{'province': '山东', 'avg_salary': 4500.0}, {'province': '河北', 'avg_salary': 5000.0}]>
    
    Python

    2、多表分组查询

    annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。
    
    总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。 
    
    # 1 查询每一个出版社的名字和出版过的书籍的平均价格
    '''
    -- sql语句:
    SELECT app01_publish.name,AVG(app01_book.price) from app01_book LEFT JOIN app01_publish on
                             app01_book.publish_id = app01_publish.id
                             group by app01_publish.id,app01_publish.name
    '''
    
    # queryset=models.Publish.objects.values("id","name").annotate(avg_price=Avg("book__price"))
    # queryset=models.Publish.objects.values("id","name","email","city").annotate(avg_price=Avg("book__price"))
    # [{"id":1,"name":"苹果出版社","eamil":"123","city":"beijing",'avg_price': 119.0},{"id":1,"name":"橘子出版社","eamil":"123","city":"beijing",'avg_price': 155.333333.0}]
    
    # queryset=models.Publish.objects.all().annotate(avg_price=Avg("book__price"))
    # print(queryset) #<QuerySet [<Publish: 苹果出版社>, <Publish: 橘子出版社>]>
    # for obj in queryset:
    #     print(obj.name,obj.avg_price)
    
    # 2 查询每一个作者的名字以及出版书籍的个数
    queryset=models.Author.objects.annotate(c=Count("book")).values("name","c")
    print(queryset) # <QuerySet [{'name': 'alex', 'c': 2}, {'name': 'egon', 'c': 2}]>
    
    # 3 查询每一个书籍的名称以及作者的个数
    queryset=models.Book.objects.annotate(c=Count("authors")).values("title","c")
    print(queryset)
    
    # 4 查询作者个数大于1 的每一本书籍的名称和作者个数
    queryset=models.Book.objects.annotate(c=Count("authors")).filter(c__gt=1).values("title","c")
    print(queryset) # <QuerySet [{'title': 'python', 'c': 2}, {'title': 'go', 'c': 2}]>
    
    # 5 查询书籍名称包含"h"的书籍名称和作者个数
    queryset=models.Book.objects.filter(title__contains="h").annotate(c=Count("authors")).values("title","c")
    
    Python

    二、F查询与Q查询

    1、F查询(作用:用于比较两个字段的值)

    在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。
    
    如果我们要对两个字段的值做比较,那该怎么做呢?
    
    Django 提供 F() 来做这样的比较。
    F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
    
    # F查询(仅可以对数值操作)  用于单表查询,涉及到两个变动的值进行对比,就要使用F查询
    from django.db.models import F,Q,Avg
    # 1、查询评论数大于100的文章
    # queryset=models.Article.objects.filter(comment_num__gt=100)
    # print(queryset)
    
    # 2、查询评论数大于点赞数的文章
    # queryset=models.Article.objects.filter(comment_num__gt=F("poll_num"))
    #                                 # 本来要写一个固定的数字,用F以后就可以使用一个变动的值
    # print(queryset)
    
    # 3、查询点赞数大于两倍的评论数的文章
    # queryset=models.Article.objects.filter(poll_num__gt=F("comment_num")*2)
    # print(queryset)    # 对F得到的结果可以在进行数据运算
    
    # 4、将所有的书籍的价格提高100元
    # models.Book.objects.all().update(price=F("price")+100)
    # print("???????你好")
    
    Python

    2、Q查询(filter方法中,运用与或非)

    filter() 等方法中的关键字参数查询都是一起进行“AND” 的。
    如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
    & | ~  对应 与或非
    
    # Q查询  可以通过与或非,将各种条件组合起来
    
    # 5、查询价格大于300或者书籍名字以p开头的书籍
    queryset=models.Book.objects.filter(price__lt=30)
    # queryset=models.Book.objects.filter(Q(title__startswith="p") | Q(price__gt=30))
    # print(queryset)
    
    
    # 6、查询价格大于300或者不是2019年1月份的书籍
    # q=Q(price__gt=300)|~Q(Q(pub_date__year=2019)&Q(pub_date__month=1))
    # queryset=models.Book.objects.filter(q)
    # print(queryset)
    
    
    
    # F与Q联合查询,
    # 点赞大于评论数的文章或者是评论数超过200文章
    queryset=models.Article.objects.filter(Q(poll_num__gt=F("comment_num"))|Q(comment_num__gt=200))
    print(queryset)
    
    Python

    1、查询函数可以混合使用Q 对象和关键字参数。

    所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。
    但是,如果出现Q 对象,它必须位于所有关键字参数的前面。
    例如:
    
    bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),
                                  title__icontains="python"
                                 )
  • 相关阅读:
    mysql 查询优化
    图解Java常用数据结构(一)
    mybatis 详解(五)------动态SQL
    Mybatis的ResultMap的使用
    java系统变慢的优化简略步骤
    mysql基本操作
    mysql数据库的优化 一
    tomcat的启动启动与关闭
    vueJs的简单入门以及基础语法
    Oracle常用命令-用户、表空间、赋权限、导入导出
  • 原文地址:https://www.cnblogs.com/yipianshuying/p/10252581.html
Copyright © 2020-2023  润新知