聚合具有相同字段值的查询项

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 将进行的查询。

以上是关于聚合具有相同字段值的查询项的主要内容,如果未能解决你的问题,请参考以下文章

pandas-对列中具有相同值的连续行进行分组和聚合

如何对具有聚合函数的 Oracle 查询进行分组

具有多个排除项的 Elasticsearch 聚合查询

Elasticsearch 中的术语聚合返回单词而不是完整字段值的存储桶

无法在具有聚合值的 HAVING 子句中使用来自子查询表连接的单值列

聚合具有特定值的两行之间的行