我们运行Postgres9.6.5和Django2.0。我们有一个Model
字段created_at
和value
。我们需要计算某个date_range
的90天移动平均值。我们就是这样做的:
output = []
for i in range(len(date_range)):
output.append(
Model.objects.filter(
created_at__date__range=(date_range[i]-timezone.timedelta(days=90), date_range[i]),
).aggregate(Avg('value'))['value__avg'].days
)
这使用了
Avg
聚合函数,因此它相当快,但是我们需要对date_range
中的每个日期进行一次查询。对于较长的范围,这意味着要进行大量的查询。Postgres can do this in a single query。我的问题是-我们能不能用Django ORM在一个查询中做到这一点?
(我知道我可以用Django ORM执行原始SQL,但如果可能的话,我想避免这种情况,这就是我问的原因。)
最佳答案
假设每个日期只有一个条目,那么可以使用Django 2.0的新窗口表达式计算单个查询中90个周期的移动平均值:
from django.db.models import Avg, F, RowRange, Window
items = Model.objects.annotate(
avg=Window(
expression=Avg('value'),
order_by=F('created_at').asc(),
frame=RowRange(start=-90,end=0)
)
)
如果您希望改为按特定字段值框显,请参见ValueRange,例如,如果您每天有多行,这可能会很方便。