【Django Models】Django数据查询 汇聚

参见官方文档 ,表定义

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_books
 

2.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
3
 

4.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}

 
 
 
posted @ 2016-06-12 15:58  inns  阅读(266)  评论(0编辑  收藏  举报