Django筆記十六之aggregate聚合操作

2023-04-06 06:01:18

本文首發於微信公眾號:Hunter後端
原文連結:Django筆記十六之aggregate聚合操作

這一篇筆記介紹一下關於聚合的操作,aggregate。

常用的聚合操作比如有平均數,總數,最大值,最小值等等

用到的 model 如下



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


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


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, on_delete=models.CASCADE)
    pubdate = models.DateField()


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

聚合函數

  • Avg —— 平均數
  • Count —— 總數
  • Max —— 最大值
  • Min —— 最小值
  • Sum —— 總數

output_field —— 指定輸出的資料格式

以下介紹一下幾種聚合操作的例子,因為 Avg,Max,Min 都是一樣的操作方法,所以用一個函數來做範例。

獲取表中最大值:

from django.db.models import Max, Min, Avg

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

對應的 SQL 為:

select avg(price) from blog_book;

返回的值為:

{'price__avg': Decimal('5.500000')}

指定聚合型別返回

因為 Book 中的 price 欄位是 Decimal 欄位,所以聚合之後返回的資料型別也是這個型別,如果想要更換成 Float 型別,可以用上 output_field 來指定輸出型別:

Book.objects.all().aggregate(Avg('price', output_field=models.FloatField()))

返回的結果就是:

{'price__avg': 5.5}

指定聚合欄位名稱

Book.objects.aggregate(avg_price=Avg("price"))

以上用的範例都是 Avg 平均數,更換成 最大值 Max,最小值 Min 都是可以的

多個聚合操作

假設我們不止需要平均數,還需要最大值,最小值等等,我們可以在一個語句裡直接操作

from django.db.models import Avg, Max, Min
Book.objects.aggregate(avg_price=Avg("price"), max_price=Max("price"), min_price=Min("price"))

關聯表的聚合操作

對於 Store model,他有一個多對多的 book 的關係,如果想獲取 Store 資料裡,關聯的 Book 的最大的 Book 的 price 資料:

Store.objects.aggregate(min_price=Min("books__price"))

如果有多個錶鏈式關聯,也可以直接鏈式聚合獲取:

Store.objects.aggregate(youngest_age=Min("books__authors__age"))

以上就是本篇筆記的全部內容,其實還有一些聚合的操作,是關於 annotate 的一些用法範例,這裡不多贅述,有時間可以單獨開一個專門的筆記。

下一篇筆記將會對 SQL 中的 group by 用法在Django 中的對應操作做一個整體介紹。

如果想獲取更多相關文章,可掃碼關注閱讀: