django

Django 1.6 Models (IV) — Aggregation

继续学习 Django,其实很多基础的东西还没有解决。

这节学到 Model 的 Aggregation 部分,即是有关 group by 的内容,而在前面的部分是没有工具可以做一些类似于 group by 以及聚合函数之类的工作的(除了直接写 sql)

这一节主要介绍了三个有用的聚合函数工具,aggregation、annotate 以及 values,用这三个函数的组合加上基本的聚合函数(Max Min Count 等等)基本可以构造出绝大部分我们实际需要的查询。

一、聚合函数 aggregation

django.db.models 命名空间里,提供了一系列的聚合函数(诸如 Count/Max/Min/Avg 等等详细查文档)

然后例如下面这个调用:

User.objects.all().aggregate(grpcnt=Count('groups'))

就可以获取到在这个 queryset 上面的平均价格,返回 {‘grpcnt’: 71}。

aggregation 的特性是,它作用在 QuerySet 上,然后返回一个 dict,其中 key 是命名参数给定的别名或者自动生成的字段加双下划线再加聚合函数名(如果本例不指定这个 grpcnt 别名的时候应该会自动生成一个 groups__count 作为键名)。

二、附加函数 annotate(增加字段)

annotate 也是聚合,但有所不同:它从一个 QuerySet 调用,然后返回一个 QuerySet,但是聚合的结果作为一个命名属性附加在原有的 QuerySet 上面,并且将原有的 QuerySet 分组聚合。

简单的理解,就是说 annotate 只是在原有的 queryset 基础上附加一个通过聚合计算的字段,返回的还是 QuerySet,而这个 QuerySet 还可以进行后续的筛选排序等等操作。

与 aggregate 的主要区别是一个是向量 (QuerySet) 到标量,一个是向量到向量。

三、取值函数 values(选取字段)

还有一个有用的函数 values,问题源自这里,有时候我们聚合的时候可能不一定要按照主键来进行聚合,例如我们想统计员工里面不同姓的人数,那我们在 annotate 之前,就必须将一些不相干的字段剔除掉。

类比参照一下,我们写 sql 查询的时候的 group by 子句会指定一系列的字段,但是这些字段很可能是与对象的主键没有关系的。

那么 django 提供了一个 values 函数,调用之会产生一个叫做 django.db.models.query.ValuesQuerySet 的 QuerySet(相应的以前理解的 QuerySet 是 django.db.models.query.QuerySet)

这个 ValuesQuerySet 也是一个 QuerySet 迭代器,不同的是它的元素不是一个 Models 对象,而是一个 dict,我们通过在一个 QuerySet 上面调用 values 函数,通过无命名参数顺序提供字段名,就可以产生一个 ValuesQuerySet。在 ValuesQuerySet 上面同样可以使用各种的 orderby 和 filter。

qs.values(‘field1’, ‘field2’) 相当于我们在 sql 查询里面使用一个 select field1, field2 from … 的查询

然后我们在上面调用 annotate 或者 aggregate,就可以按照 ValuesQuerySet 的字段组合 groupby 之后产生的聚合了。


【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2014/05/django-models-4.html【Django 1.6 Models (IV) — Aggregation】

发表评论

电子邮件地址不会被公开。 必填项已用*标注