zoukankan      html  css  js  c++  java
  • 聚合和分组

    1、准备数据库环境,比之前增加了price字段

    class Publisher(models.Model):
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return '<Publisher: {} - {}>'.format(self.pk, self.name)
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5,decimal_places=2)  #最大999.99
        publisher = models.ForeignKey('Publisher',related_name='books',related_query_name='book',on_delete=models.CASCADE)
    
        def __str__(self):
            return '<Book: {} - {}>'.format(self.pk, self.title)
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField('Book')  #多对多创建,后面是要关联的表Book类

     聚合

    import os
    
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
        import django
    
        django.setup()
    
        from app01 import models
    
        from django.db.models import Max,Min,Sum,Avg,Count
    
        # ret = models.Book.objects.aggregate(Max('price')) #aggregate本身就是聚合
        ret = models.Book.objects.all().aggregate(Min('price'),Avg('price'),max=Max('price')) #aggregate本身就是聚合
        # print(ret) #{'price__max': Decimal('99.00'), 'price__min': Decimal('10.00'), 'price__avg': 68.5}

    分组

    import os
    
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
        import django
    
        django.setup()
    
        from app01 import models
    
        from django.db.models import Max,Min,Sum,Avg,Count
    
        # ret = models.Book.objects.aggregate(Max('price')) #aggregate本身就是聚合
        ret = models.Book.objects.all().aggregate(Min('price'),Avg('price'),max=Max('price')) #aggregate本身就是聚合
        # print(ret) #{'price__max': Decimal('99.00'), 'price__min': Decimal('10.00'), 'price__avg': 68.5}
    
        # 按照出版社进行分组,聚合字段不再我这,我用跨表book__price  最后的values是取我的querySet里面的字段和对应的值
        ret = models.Publisher.objects.annotate(Avg('book__price')).values() #annotate:注释 把做完的结果塞到对象里面了
        # print(ret)
    
        #按照书做分组 再以publisher__name做二次分组
        # ret = models.Book.objects.values('publisher__name').annotate(avg=Avg('price'))
        # # print(ret)
        # for i in ret:
        #     print(i)
    
        #统计一本书作者的个数
        # ret = models.Book.objects.annotate(author_num=Count('author'))
        # for i in ret:
        #     print(i.author_num)
    
        # 统计出每个出版社买的最便宜的书的价格
        # 方法一:
        # ret = models.Publisher.objects.annotate(Min('book__price')).values()
        # for i in ret:
        #     print(i)
    
        #方法二:按照书分组 指定values,指定以publisher做了分组的字段
        # ret = models.Book.objects.values('publisher').annotate(Min('price'))
        # for i in ret:
        #     print(i)
    
        #统计不止一个作者的图书
        # ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
        # for i in ret:
        #     print(i)  #<Book: 2 - 葵花宝典>

     

    我们在这里先复习一下SQL语句的分组。

    假设现在有一张公司职员表:

     我们使用原生SQL语句,按照部门分组求平均工资:

    select dept,AVG(salary) from employee group by dept;

    ORM查询:

    from django.db.models import Avg
    Employee.objects.values("dept").annotate(avg=Avg("salary").values("dept", "avg")

    连表查询的分组:

    SQL查询:

    select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;

    ORM查询:

    from django.db.models import Avg
    models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")

    更多示例:

    示例1:统计每一本书的作者个数

    复制代码
    >>> book_list = models.Book.objects.all().annotate(author_num=Count("author"))
    >>> for obj in book_list:
    ...     print(obj.author_num)
    ...
    2
    1
    1
    复制代码

    示例2:统计出每个出版社买的最便宜的书的价格

    >>> publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price"))
    >>> for obj in publisher_list:
    ...     print(obj.min_price)
    ...     
    9.90
    19.90

    方法二:

    >>> models.Book.objects.values("publisher__name").annotate(min_price=Min("price"))
    <QuerySet [{'publisher__name': '沙河出版社', 'min_price': Decimal('9.90')}, {'publisher__name': '人民出版社', 'min_price': Decimal('19.90')}]>

    示例3:统计不止一个作者的图书

    >>> models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1)
    <QuerySet [<Book: 番茄物语>]>

    示例4:根据一本图书作者数量的多少对查询集 QuerySet进行排序

    >>> models.Book.objects.annotate(author_num=Count("author")).order_by("author_num")
    <QuerySet [<Book: 香蕉物语>, <Book: 橘子物语>, <Book: 番茄物语>]>

    示例5:查询各个作者出的书的总价格

    >>> models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")
    <QuerySet [{'name': '小精灵', 'sum_price': Decimal('9.90')}, {'name': '小仙女', 'sum_price': Decimal('29.80')}, {'name': '小魔女', 'sum_price': Decimal('9.90')}]>
  • 相关阅读:
    C#根据长度创建数组
    PLC读取数据高低位交换,批量保存到list集合,方便调用。
    C#读取图片流保存到文件,再读取流文件,把图片再显示出来
    C#从SQL server数据库中读取l图片和存入图片[转]
    C# 数据库查询表字段,写入到combox
    C# MSSQL数据库查询SQL语句拼接
    C# winform只允许程序运行一个
    C# 定时关机代码
    C#用委托来动态显示日期和时间
    使用margin负值实现压住相邻边距
  • 原文地址:https://www.cnblogs.com/wangkaiok/p/10493306.html
Copyright © 2011-2022 走看看