• Django 统计查询


    一、整个查询集统计

    Django 提供两种方法来产生统计。

    第一种方法是产生整个 查询集 的统计。假设我们要统计所有书的平均价格。 Djnago 中查询所有书的语句为:

    >>> Book.objects.all()

    在这个语句后加上一个 aggregate() 子句就行了:

    >>> from django.db.models import Avg

    >>> Book.objects.all().aggregate(Avg('price'))

    {'price__avg': 34.35}

    上例中的 all() 是多余的。所以可以简写为:

    >>> Book.objects.aggregate(Avg('price'))

    {'price__avg': 34.35}

    aggregate() 子句的参数代表我们要统计的内容,本例中我们要统计 Book 模型中 price 字段的平均值。

    aggregate() 是一个 查询集 的未端子句,调用后会返回一个由名称-值配对组成的字典。名称是指统计的名称,值就是统计的值。名称由字段名称配双下划线加上函数名自动组成。如果你想手动指定统计名称,可以象下例在统计子句中定义:

    >>> Book.objects.aggregate(average_price=Avg('price'))

    {'average_price': 34.35}

    如果你想要生成多个统计,那么只要在统计子句后加上另外的统计子句就可以了。例如,如果要计算所有书价中最高价和最低价,可以这样写:

    >>> from django.db.models import Avg, Max, Min, Count, Sum

    >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))

    {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

    二、生成查询集中每一个项目的统计

    第二种方法是为 查询集 中每个独立的对象生成统计。例如,当你检索一个书单时,可能想知道每本书有几个作者。每本书与每个作者之间是一个多对多的关系,我们要为每本书总结这个关系。

    要产生每个对象的统计可以使用 annotate() 子句。当定义一个 annotate() 子句后, 查询集 中的每个对象就可以与特定值关联,相当于每个对象有一个 “注释”。

    这种注释的语法与 aggregate() 相同。 annotate() 的每个参数代表一个统计。例如,要计算每本书的作者人数:

    >>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price')) 

    联合的深度是无限的。例如,要统计所有书的作者的最小年龄,你可以这样: 

    >>> Store.objects.aggregate(youngest_age=Min('books__authors__age')) 

    三、统计和其他查询子句 

    filter() 和 exclude()

    在过滤器中也可以使用统计。任何用于一般模型的 filter() (或 exclude() )也可与统计联用。

    当与 annotate() 子句联用时,过滤器作用于被统计的对象上。例如要统计书名以 "Django" 开头的书: 

    >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors')) 

    当与 aggregate() 子句联用时,过滤器作用于被统计的所有对象上。例如要统计书名以 "Django" 开头的书的平均价格: 

    >>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price')) 

    过滤统计的值

    统计出来的值也可以被过滤。和其他模型一样,统计的结果也可以使用 filter() 和 exclude() 子句来过滤。

    例如,要产生一个由两个以上作者的书单可以这样:

    >>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)

    上例先进行统计,然后在统计的结果上使用了过滤器。 

    annotate() 和 filter() 子句的顺序

    当使用同时包含 annotate() 和 filter() 子句的复杂查询时,要特别小心两种子句的顺序。

    当一个 annotate() 子句作用于查询时,该统计只对子句之前的查询起作用。也就是说 filter() 和 annotate() 顺序不同,查询就不同了。查询:

    >>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0)

    和查询:

    >>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))

    是不同的。两个查询都会返回至少有一本好书(评分大于 3.0 )的出版商。但是,第一个查询中的统计会提供出版商的所有书的数量;第二个查询中的统计只返回好书的数量。第一个查询中统计先于过滤器,所以过滤器对统计没有作用。而第二个查询过滤器先于统计,所以统计的对象是已经过滤过的。

    order_by()

    统计可以作为排序的基础。当你定义一个 order_by 子句时,可以引用 annotate() 子句中的统计。

    例如,要依据书的作者人数进行排序,可以这样:

    >>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')

  • 相关阅读:
    【原创】flash中DataGrid数据列显示顺序的解决办法(非数据排序)
    [译]C# 7系列,Part 2: Async Main 异步Main方法
    [译]C# 7系列,Part 1: Value Tuples 值元组
    我们是怎么做Code Review的
    Asp.Net 5 新增公告仓库
    微信现金红包高级红包接口开发注意事项
    解决Windows 8.1中所有的应用(Modern App)无法打开(闪退)的问题
    代码要恰如其分——记一次代码审查
    [译]DbContext API中使用SqlQuery和ExecuteSqlCommand获取存储过程的输入输出参数
    解决托管在Windows上的Stash的Pull request无法合并的问题
  • 原文地址:https://www.cnblogs.com/shiqi17/p/12533208.html
Copyright © 2020-2023  润新知