Django Aggregation数据库聚合查询

在当今根据需求而不断调整而成的应用程序中,通常不仅需要能依常规的字段,如字母顺序或创建日期,来对项目进行排序,还需要按其他某种动态数据对项目进行排序。Djngo聚合就能满足这些要求。

以下面的Model为例

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()

class Publisher(models.Model):
    name = models.CharField(max_length=300)
    num_awards = models.IntegerField()

class Book(models.Model):
    name = models.CharField(max_length=300)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    rating = models.FloatField()
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    pubdate = models.DateField()

class Store(models.Model):
    name = models.CharField(max_length=300)
    books = models.ManyToManyField(Book)
    registered_users = models.PositiveIntegerField()

快速了解

# books总数量.
>>> Book.objects.count()
2452

# Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name=‘BaloneyPress‘).count()
73

# books的平均price.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg(‘price‘))
{‘price__avg‘: 34.35}

# books的最大price.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max(‘price‘))
{‘price__max‘: Decimal(‘81.20‘)}

# All the following queries involve traversing the Book<->Publisher
# many-to-many relationship backward

# 为每个publisher添加个num_books属性,即每个pulisher出版的book的数量.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count(‘book‘))
>>> pubs
[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
>>> pubs[0].num_books
73

# 根据num_book属性排序.
>>> pubs = Publisher.objects.annotate(num_books=Count(‘book‘)).order_by(‘-num_books‘)[:5]
>>> pubs[0].num_books
1323

聚合生成Generating aggregates over a QuerySet

Django有两种方法来生成聚合。第一种方法是为整个QuerySet生成聚合值,例如为全部的books生成price的平均值:

>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg(‘price‘))
{‘price__avg‘: 34.35}

可以简略为:

>>> Book.objects.aggregate(Avg(‘price‘))
{‘price__avg‘: 34.35}

函数aggregate()的参数是一系列聚合函数aggregate functions:

Avg

返回平均值

Count
  class Count(field, distinct=False)

返回计数。当参数distinct=True时,返回unique的对象数目。

Max

返回最大值

Min

返回最小值.

StdDev
  class StdDev(field, sample=False)
返回标准偏差

有一个参数sample

默认情况下sample=False,返回总体标准偏差,如果sample=True,返回样本标准偏差。

Sum

返回总值

Variance
  class Variance(field, sample=False)
返回方差

有一个参数sample,默认返回总体方差,sample设为True时返回样本方差。

aggregate()方法被调用时,返回一个键值对字典,可以指定key的名字:

>>> Book.objects.aggregate(average_price=Avg(‘price‘))
{‘average_price‘: 34.35}

如果你想生成多个聚合,你只需要添加另一个参数。所以,如果我们还想知道所有书的最高和最低的价格:

>>> 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‘)}

为查询集的每个对象生成聚合值Generating aggregates for each item in a QuerySet

这是生成聚合值的第二种方法。比如你要检索每本书有多少个作者。book和author是manytomany的关系,我们可以为每本书总结出这种关系。

每个对象的总结可以用方法annotate()生成:

# 建立一个annotate QuerySet
>>> from django.db.models import Count
>>> q = Book.objects.annotate(Count(‘authors‘))
# 第一个对象
>>> q[0]
<Book: The Definitive Guide to Django>
>>> q[0].authors__count
2
# 第二个对象
>>> q[1]
<Book: Practical Django Projects>
>>> q[1].authors__count
1

 也可以指定生成属性的名字:

>>> q = Book.objects.annotate(num_authors=Count(‘authors‘))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

和aggregate()不同,annotate()的输出是一个QuerySet。

联合聚合Joins and aggregates

目前为止,我们聚合查询的field都属于我们要查询的Model,我们也可以用其它Model的field来进行聚合查询,例如:

>>> from django.db.models import Max, Min
>>> Store.objects.annotate(min_price=Min(‘books__price‘), max_price=Max(‘books__price‘))

这样就可以查询每个Store里面所有books的价格范围

联合链的深度可以随心所欲:

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

反向关系Following relationships backwards

通过book反向查询publisher:

>>> from django.db.models import Count, Min, Sum, Avg
>>> Publisher.objects.annotate(Count(‘book‘))

返回的QuerySet的每个publisher都会带一个属性book_count。

查询出版最久的书的出版日期:

>>> Publisher.objects.aggregate(oldest_pubdate=Min(‘book__pubdate‘))

查询每个作者写的书的总页数:

>>> Author.objects.annotate(total_pages=Sum(‘book__pages‘))

查询所有作者写的书的平均rating:

>>> Author.objects.aggregate(average_rating=Avg(‘book__rating‘))

聚合和其它查询集操作Aggregations and other QuerySet clauses

filter() and exclude()

聚合可以和filter和exclude一起使用:

>>> from django.db.models import Count, Avg
>>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count(‘authors‘))
>>> Book.objects.filter(name__startswith="Django").aggregate(Avg(‘price‘))

可以根据聚合值进行筛选:

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

顺序的不同,产生的意义也不同:

>>> 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‘))

都返回一个QuerySet,前者计算的是全部书的数量,后者只计算好书的数量。

order_by()

可以根据聚合值进行排序:

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

values()

>>> Author.objects.values(‘name‘).annotate(average_rating=Avg(‘book__rating‘))

这样的写法下,QuerySet会根据name进行组合,返回的是每个unique name的聚合值。如果有两个作者有相同的名字,这两个作者会被当做一个计算,他们的books会合在一起。

>>> Author.objects.annotate(average_rating=Avg(‘book__rating‘)).values(‘name‘, ‘average_rating‘)

位置互换后,会为每个author都生成一个average_rating,而且只会输出每个author的name和average_rating。

默认排序下使用聚合:

from django.db import models

class Item(models.Model):
    name = models.CharField(max_length=10)
    data = models.IntegerField()

    class Meta:
        ordering = ["name"]

如果想计算每个不同的data的数量,你可能这样写:

# Warning: 不正确的写法
Item.objects.values("data").annotate(Count("id"))

 因为query会根据(data,name)对进行组合,你需要这样写来去除默认排序的影响:

Item.objects.values("data").annotate(Count("id")).order_by()

Aggregating annotations

也可以根据annotation结果生成聚合值,例如计算每本书平均有几个作者:

>>> from django.db.models import Count, Avg
>>> Book.objects.annotate(num_authors=Count(‘authors‘)).aggregate(Avg(‘num_authors‘))
{‘num_authors__avg‘: 1.66}

  

Django Aggregation数据库聚合查询

时间: 2024-11-06 07:34:22

Django Aggregation数据库聚合查询的相关文章

Django Mysql数据库-聚合查询与分组查询

一.聚合查询与分组查询(很重要!!!) 聚合查询:aggregate(*args, **kwargs),只对一个组进行聚合 from django.db.models import Avg,Sum,Count,Max,Min # 1.查询所有图书的平均价格 print(models.Book.objects.all().aggregate(Avg("price"))) aggregate()是QuerySet 的一个终止子句(也就是返回的不再是一个QuerySet集合的时候),意思是说

Django框架08 /聚合查询、分组、F查询和Q查询、执行原生sql、设置 sql_mode

目录 Django框架08 /聚合查询.分组.F查询和Q查询.执行原生sql.设置 sql_mode 1.聚合查询 2.分组 3.F查询和Q查询 4.执行原生sql(了解) 5.展示sql的 6.设置 sql_mode Django框架08 /聚合查询.分组.F查询和Q查询.执行原生sql.设置 sql_mode 1.聚合查询 aggregate(*args, **kwargs) aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典.键的名称是聚合值

django操作数据库之查询F,Q操作 和 seach搜索功能

# F 使用查询条件的值 # # from django.db.models import F # models.Tb1.objects.update(num=F('num')+1) # Q 构建搜索条件 from django.db.models import Q # con = Q() # # q1 = Q() # q1.connector = 'OR' # q1.children.append(('id', 1)) # q1.children.append(('id', 10)) # q1

Django基础—— 14.聚合查询和分组查询

原文地址:https://www.cnblogs.com/yz9110/p/9338972.html

django指定mysql数据库 ORM查询

django原生自带数据库,不过自带的数据库是sqlite 这次使用的orm框架操作数据库 这时候你就需要换上你想用的数据库比如大众化的mysql 但是你还是首先要先安装pymysql的驱动 pip install PyMySQL 在Django的工程同名子目录的__init__.py文件中添加如下语句 from pymysql import install_as_MySQLdb install_as_MySQLdb()django 在python2.7一直使用的是db操作数据库由于django

Django学习【第7篇】:Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)

django之跨表查询及添加记录 一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建多对多的关系:ManyToMany(&qu

Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)

一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建多对多的关系:ManyToMany("要绑定关系的表名"

python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)

12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_demo.settings") import django django.setup() # 启动Django项目 from app01 import models #返回QuerySet对象的方法: r

Django Aggregation聚合

Django有两种方法来生成聚合.第一种方法是为整个QuerySet生成聚合值,例如为全部的books生成price的平均值: >>> from django.db.models import Avg>>> Book.objects.all().aggregate(Avg('price')){'price__avg': 34.35} 可以简略为: >>> Book.objects.aggregate(Avg('price')){'price__avg'