聚合具有相同字段值的查询项
Posted
技术标签:
【中文标题】聚合具有相同字段值的查询项【英文标题】:Aggregating query items with the same field value 【发布时间】:2020-03-07 09:25:00 【问题描述】:我的一个查询集返回包含多个字段的项目列表:
<QuerySet ['name': 'John', 'products': 4, 'name': 'John', 'products': 6, 'name': 'Sam', 'products': 7, ...]>
我如何聚合这些数据以获取具有相同 name
字段的元素的 Sum()
和 products
值的组合,以避免在查询集中出现重复,因此我会得到这样的结果:
<QuerySet ['name': 'John', 'products': 10, 'name': 'Sam', 'products': 7, ...]>
我知道这应该使用 .annotate()
或 .aggregate()
查询来完成,但我不知道如何。
【问题讨论】:
【参考方案1】:你需要的是annotate
,你可以这样做:
from django.db.models import Sum
your_queryset = YourModel.objects.annotate(total_products=Sum('products')).values_list('name', 'total_products')
您可以通过查看docs了解更多信息
【讨论】:
【参考方案2】:你可以构造这样的查询集:
from django.db.models import Sum
Model.objects.values('name').annotate(
sum_products=Sum('products')
).order_by('name')
.order_by(..)
是强制 Django 使用 GROUP BY 子句所必需的。
【讨论】:
我知道.values('name')
应该在.annotate()
子句之前,但究竟为什么呢?它是否告诉查询哪个字段用于分组?其背后的一般机制是什么?
@StanRedoute:完全正确。您需要指定将在选择部分中使用的值。 .annotate(..)
中的会自动添加。
但是为什么查询中.values()
的顺序如此重要?我注意到,如果我在 .order_by()
之前将其移到末尾 - 查询返回的结果会略有不同(差异足以使其无法使用)。
@StanRedoute:因为这样您将在 GROUP BY 中考虑所有值。大多数 Django 操作都是“顺序敏感的”。您可以使用print(Model.objects.values(..).query)
打印 Django 将进行的查询。以上是关于聚合具有相同字段值的查询项的主要内容,如果未能解决你的问题,请参考以下文章
Elasticsearch 中的术语聚合返回单词而不是完整字段值的存储桶