使用 django 的 ORM annotate()
和/或aggregate()
:我想根据一个类别字段进行汇总,然后平均每个日期的类别值。我尝试使用两个annotate()
语句来做到这一点,但得到了一个FieldError
.
我正在这样做:
queryset1 = self.data.values('date', 'category').annotate(sum_for_field=Sum('category'))
它输出一个ValuesQuerySet
对象,其中包含以下内容(因此类别的每个值的总和):
[{'category': 'apples', 'date': '2015-10-12', sum_for_field=2000},
{'category': 'carrots', 'date': '2015-10-12', sum_for_field=5000},
{'category': 'apples', 'date': '2015-10-13', sum_for_field=3000},
{'category': 'carrots', 'date': '2015-10-13', sum_for_field=6000}, ...
]
然后,我想平均每个日期的sum_for_field
字段以输出如下内容:
[ {'date': '2015-10-12', avg_final: 3500},
{'date': '2015-10-13', avg_final: 4500}, ...
]
我尝试这样做:
queryset2 = queryset1.values('date', 'sum_for_field')
result = queryset2.annotate(avg_final=Avg('sum_for_field'))
但我得到了这个FieldError
:
FieldError: FieldError: Cannot compute Avg('sum_for_field'): 'sum_for_field' is an aggregate
从许多聚合批注中按组聚合批注通常是一个复杂的问题,但Sum
Avg
是一个特殊得多的情况。
表达式Avg('sum_for_field')
可以计算为可由 Aggregate() 表达式计算的Sum('sum_for_field') / Count('category', distinct=True)
。Sum('sum_for_field')
等于Sum('amount')
。
解决方案:(预期名称:模型Data
具有字段 date
、 category
、 amount
。
qs = Data.objects.values('date').annotate(
avg_final=Sum('amount') / Count('category', distinct=True)
)
(我相信非常相似的问题在当前的 Django 1.11 中没有任何解决方案,即使使用 Subquery 类,也没有使用奇怪的 extra() 方法,也没有原始 SQL)
我没有深入研究,但我怀疑当您使用没有注释的values()
时,sum_for_field
值正在与共享相同date
的值合并。我认为您需要在使用values()
子句后立即评估注释。也许下面这样的事情可以解决您的问题:
result = queryset1.values('date').annotate(avg_final=Avg('sum_for_field'))