Django2.0-db(7)-查询操作-聚合函数

笔记在知了课堂-Django开发的基础上更改

反向查询和反向引用

  • 反向查询: 将模型名字小写化。 比如article_in。可以通过related_query_name来指定名字。
  • 反向引用: 将模型名字小写化,加上_set。比如article_set,可以通过related_name来指定自己的方式。

聚合函数

  • 如果你用原生SQL,则可以使用聚合函数来提取数据。比如提取某个商品销售的数量,那么可以使用Count,如果想要知道商品销售的平均价格,那么可以使用Avg
  • 聚合函数不能单独执行,需要放在一些可以执行聚合函数的方法下面中去执行。比如aggregate方法来实现的。
  • 聚合函数执行完毕之后,Django默认给聚合函数的值取个名字。命名规则是filed名+__+聚合函数名
  • 在讲解这些聚合函数的用法的时候,都是基于以下的模型对象来实现的。
  from django.db import models

 class Author(models.Model):
     """作者模型"""
     name = models.CharField(max_length=100)
     age = models.IntegerField()
     email = models.EmailField()

     class Meta:
         db_table = 'author'


 class Publisher(models.Model):
     """出版社模型"""
     name = models.CharField(max_length=300)

     class Meta:
         db_table = 'publisher'


 class Book(models.Model):
     """图书模型"""
     name  = models.CharField(max_length=300)
     pages = models.IntegerField()
     price = models.FloatField()
     rating = models.FloatField()
     author = models.ForeignKey(Author,on_delete=models.CASCADE)
     publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

     class Me ta:
         db_table = 'book'


 class BookOrder(models.Model):
     """图书订单模型"""
     book = models.ForeignKey("Book",on_delete=models.CASCADE)
     price = models.FloatField()

     class Meta:
         db_table = 'book_order'

Avg

求平均值。比如想要获取所有图书的价格平均值。那么可以使用以下代码实现。

 from django.db.models import Avg
 result = Book.objects.aggregate(Avg('price'))
 print(result)

以上的打印结果是:

 {"price__avg":23.0}

其中price__avg的结构是根据field__聚合函数名规则构成的。如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数。示例代码如下:

 from django.db.models import Avg
 result = Book.objects.aggregate(my_avg=Avg('price'))
 print(result)

那么以上的结果打印为:

 {"my_avg":23}

Count

获取指定的对象的个数。示例代码如下:

 from django.db.models import Count
 result = Book.objects.aggregate(book_num=Count('id'))

以上的result将返回Book表中总共有多少本图书。
Count类中,还有另外一个参数叫做distinct,默认是等于False,如果是等于True,那么将去掉那些重复的值。比如要获取作者表中所有的不重复的邮箱总共有多少个,那么可以通过以下代码来实现:

     from djang.db.models import Count
     result = Author.objects.aggregate(count=Count('email',distinct=True))

Max和Min

获取指定对象的最大值和最小值。比如想要获取Author表中,最大的年龄和最小的年龄分别是多少。那么可以通过以下代码来实现:

 from django.db.models import Max,Min
 result = Author.objects.aggregate(Max('age'),Min('age'))

如果最大的年龄是88,最小的年龄是18。那么以上的result将为:

 {"age__max":88,"age__min":18}

Sum

求指定对象的总和。比如要求图书的销售总额。那么可以使用以下代码实现:

 from djang.db.models import Sum
 result = Book.objects.annotate(total=Sum("bookstore__price")).values("name","total")

以上的代码annotate的意思是给Book表在查询的时候添加一个字段叫做total,这个字段的数据来源是从BookStore模型的price的总和而来。values方法是只提取nametotal两个字段的值。

更多的聚合函数请参考官方文档:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#aggregation-functions

aggregate和annotate的区别

  1. aggregate:返回使用聚合函数后的字段和值。返回一个dict

  2. annotate:**返回一个QuerySet。**在原来模型字段的基础之上添加一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组(group by)。
    比如以上Sum的例子,如果使用的是annotate,那么将在每条图书的数据上都添加一个字段叫做total(这个字段看你自己设不设置,不设置就使用默认的Field__聚合方式名),计算这本书的销售总额。
    而如果使用的是aggregate,那么将求所有图书的销售总额。

  3. 都可以在任何的QuerySet对象调用

    比如要获取2018年度的销售总额,可以先过滤年份,再求聚合函数

    BookOrder.object.filter(create_time__year=2018).aggregate(total=Sun('price'))
    

猜你喜欢

转载自blog.csdn.net/abc666666_6/article/details/83931308