我们运行Postgres9.6.5和Django2.0。我们有一个Model字段created_atvalue。我们需要计算某个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,例如,如果您每天有多行,这可能会很方便。

09-30 23:55