我想按日期在模型中创建一个求和,然后添加一个滚动平均值...在一个查询中。这可能吗?
假设我有一个这样的表,叫做“销售”:
|---------------------|------------------|--------------|
| Date | Category | Value |
|---------------------|------------------|--------------|
| 2020-04-01 | 1 | 55.0 |
|---------------------|------------------|--------------|
| 2020-04-01 | 2 | 30.0 |
|---------------------|------------------|--------------|
| 2020-04-02 | 1 | 25.0 |
|---------------------|------------------|--------------|
| 2020-04-02 | 2 | 85.0 |
|---------------------|------------------|--------------|
| 2020-04-03 | 1 | 60.0 |
|---------------------|------------------|--------------|
| 2020-04-03 | 2 | 30.0 |
|---------------------|------------------|--------------|
我想按日期分组(“类别”列不重要),并添加日期值的总和。然后我想添加一个最近7天的滚动平均值。
我试过这个:
days = (
Sales.objects.values('date').annotate(sum_for_date=Sum('value'))
).annotate(
rolling_avg=Window(
expression=Avg('sum_for_date'),
frame=RowRange(start=-7,end=0),
order_by=F('date').asc(),
)
)
.order_by('date')
这会抛出此错误:
django.core.exceptions.FieldError: Cannot compute Avg('sum_for_date'): 'sum_for_date' is an aggregate
有什么想法吗
2条答案
按热度按时间vvppvyoh1#
您得到的错误是因为您试图计算同一查询中聚合字段(“sum_for_date”)的平均值。这在Django的ORM中是不可能的。
一种可能的解决方法是使用子查询计算每日总和,然后使用另一个查询计算滚动平均值。下面是一个使用销售模型的示例:
它首先使用子查询计算每日总和,然后使用窗口函数计算滚动平均值。rolling_sum窗口函数计算前7天的总和,rolling_count窗口函数计算前7天的日期计数。最后,我们将rolling_sum除以rolling_count以获得滚动平均值。
请注意,此方法使用仅在某些数据库中可用的Window函数(例如PostgreSQL)。如果您使用的是不同的数据库,则可能需要使用不同的方法来计算滚动平均值。
关于
Window
的更多信息:https://docs.djangoproject.com/en/dev/ref/models/expressions/#window-functions91zkwejq2#
出现错误的原因是您试图计算同一查询中聚合字段(“sum_for_date”)的平均值。若要解决此问题,可以使用子查询来计算滚动平均值。
你可以试试这样的