|
| 1 | +### 模型 |
| 2 | +```python |
| 3 | +from django.db import models |
| 4 | + |
| 5 | +class Author(models.Model): |
| 6 | + name = models.CharField(max_length=100) |
| 7 | + age = models.IntegerField() |
| 8 | + |
| 9 | +class Publisher(models.Model): |
| 10 | + name = models.CharField(max_length=300) |
| 11 | + |
| 12 | +class Book(models.Model): |
| 13 | + name = models.CharField(max_length=300) |
| 14 | + pages = models.IntegerField() |
| 15 | + price = models.DecimalField(max_digits=10, decimal_places=2) |
| 16 | + rating = models.FloatField() |
| 17 | + authors = models.ManyToManyField(Author) |
| 18 | + publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) |
| 19 | + pubdate = models.DateField() |
| 20 | + |
| 21 | +class Store(models.Model): |
| 22 | + name = models.CharField(max_length=300) |
| 23 | + books = models.ManyToManyField(Book) |
| 24 | +``` |
| 25 | + |
| 26 | +### 1.常见的聚合查询 |
| 27 | +```python |
| 28 | +# 查看一共有多少本书 |
| 29 | +>>> Book.objects.count() |
| 30 | +2452 |
| 31 | + |
| 32 | +# 出版社为BaloneyPress的书一共有多少 |
| 33 | +>>> Book.objects.filter(publisher__name='BaloneyPress').count() |
| 34 | +73 |
| 35 | + |
| 36 | +# 所有书的平均价格 |
| 37 | +>>> from django.db.models import Avg |
| 38 | +>>> Book.objects.all().aggregate(Avg('price')) |
| 39 | +{'price__avg': 34.35} |
| 40 | + |
| 41 | +# 所有书中价格最高的 |
| 42 | +>>> from django.db.models import Max |
| 43 | +>>> Book.objects.all().aggregate(Max('price')) |
| 44 | +{'price__max': Decimal('81.20')} |
| 45 | + |
| 46 | +# 最高价与平均价差多少 |
| 47 | +>>> from django.db.models import FloatField |
| 48 | +>>> Book.objects.aggregate(price_diff=Max('price', output_field=FloatField()) - Avg('price')) |
| 49 | +{'price_diff': 46.85} |
| 50 | + |
| 51 | +# 每个出版社出版对应数量的书 |
| 52 | +>>> from django.db.models import Count |
| 53 | +>>> pubs = Publisher.objects.annotate(num_books=Count('book')) |
| 54 | +>>> pubs |
| 55 | +<QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]> |
| 56 | +>>> pubs[0].num_books |
| 57 | +73 |
| 58 | + |
| 59 | +>>> from django.db.models import Q |
| 60 | +>>> above_5 = Count('book', filter=Q(book__rating__gt=5)) |
| 61 | +>>> below_5 = Count('book', filter=Q(book__rating__lte=5)) |
| 62 | +>>> pubs = Publisher.objects.annotate(below_5=below_5).annotate(above_5=above_5) |
| 63 | +>>> pubs[0].above_5 |
| 64 | +23 |
| 65 | +>>> pubs[0].below_5 |
| 66 | +12 |
| 67 | + |
| 68 | +# 出版数量最多的前5个出版社 |
| 69 | +>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5] |
| 70 | +>>> pubs[0].num_books |
| 71 | +1323 |
| 72 | +``` |
| 73 | + |
| 74 | +### 2.在QuerySet上聚合 |
| 75 | +* **通过在 QuerySet 后添加 aggregate() 子句来计算 QuerySet 对象的汇总值。** |
| 76 | +* 传递给aggregate()的参数描述了我们要计算的聚合值。 |
| 77 | +```python |
| 78 | +>>> Book.objects.aggregate(average_price=Avg('price')) |
| 79 | +{'average_price': 34.35} |
| 80 | +``` |
| 81 | + |
| 82 | +### 3.为QuerySet上每个条目生成聚合 |
| 83 | +**使用 annotate() 子句可以生成每一个对象的汇总。当指定 annotate() 子句,QuerySet 中的每一个对象将对指定值进行汇总。** |
| 84 | + |
| 85 | +** aggregate()s是字句,返回的是一个字典;annotate()不是终端子句,它返回的还是一个QuerySet。** |
| 86 | +```python |
| 87 | +>>> q = Book.objects.annotate(num_authors=Count('authors')) |
| 88 | +>>> q[0].num_authors |
| 89 | +2 |
| 90 | +>>> q[1].num_authors |
| 91 | +1 |
| 92 | +``` |
0 commit comments