参见官方文档 ,表定义
https://docs.djangoproject.com/en/dev/topics/db/aggregation/
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()
1. aggregate范例
1.1 统计本表数据
定义列名
Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}常用的汇聚函数有Avg,Max,Min,Count,Sum等等
1.2 F条件引入计算
Book.objects.all().aggregate(
... price_per_page=Sum(F('price')/F('pages'), output_field=FloatField()))
{'price_per_page': 0.4470664529184653}1.3 统计外键的字段
>>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price'))2. annotate
2.1 基本
可以看成是一个反向查找,外键关联汇聚统计。
注意'book'是使用了该外键,与前面表定义可能有点不符
(note how we use 'book' to specify the Publisher -> Book reverse foreign key hop)
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
<QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]>
>>> pubs[0].num_books2.2 指定字段统计
如下,指定book表的rating字段统计
Author.objects.annotate(average_rating=Avg('book__rating'))3. aggregate和annotate差别
aggregate主要是本表字段汇聚计算,annotate是外键关联汇聚计算
4. 汇聚与其他查询条件如filter
4.1 多条汇聚
distinct避免重复计算
>>> q = Book.objects.annotate(Count('authors', distinct=True), Count('store', distinct=True))
>>> q[0].authors__count
2
>>> q[0].store__count
34.2 汇聚与filter
汇聚运算和filter运算会按照书写顺序进行运算
条件在后,annotate统计的时候不考虑条件
>>> a, b = Publisher.objects.annotate(num_books=Count('book', distinct=True)).filter(book__rating__gt=3.0)
>>> a, a.num_books
(<Publisher: A>, 2)
>>> b, b.num_books
(<Publisher: B>, 2)
条件在前,annotate在过滤后的结果集上统计>>> a, b = Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))
>>> a, a.num_books
(<Publisher: A>, 2)
>>> b, b.num_books
(<Publisher: B>, 1)5. annotate和aggregate串联
Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors')){'num_authors__avg': 1.66}