我正在尝试对组内的成本进行求和,然后在多个组上添加累积成本。简化版:
class Cost(Model):
year = IntegerField()
month = IntegerField()
cost = DecimalField()
select
"year",
"month",
month_total,
sum(month_total) over (
partition by 1 order by "year", "month" rows between unbounded preceding and current row
) as cum_total
from (
select "year", "month", sum("cost") as month_total
from app_cost
group by "year", "month"
) as innerq
order by "year", "month"
但我不知道如何用 Django 的 ORM 来编写它:
innerq = Cost.objects.values("year", "month").annotate(month_total=Sum("cost"))
一切都很好,但如果我这样做:
outerq = innerq.annotate(
cum_total=Window(
expression=Sum("month_total"),
partition_by=[Value(1)],
order_by=[F("year"), F("month")],
frame=RowRange(None, 0), # UNBOUNDED PRECEDING -> CURRENT ROW
),
)
我得到:
FieldError:无法计算 Sum('month_total'):'month_total' 是一个聚合
如何将查询集
innerq
强制放入子查询中,如上面的 SQL 所示? (我知道Subquery
,我只是还没有找到在这里应用它的方法。)
我一直在为类似的问题而苦苦挣扎,刚刚发现了 django-cte 项目,该项目似乎证实了开箱即用的 ORM 没有所需的支持,并提供了一种使用其前进的方法With
。
使用它,我相信您的问题的简化版本可以通过以下方式解决:
from django_cte import With
cte = With(
Cost.objects
.values("year", "month", "month_total")
.annotate(month_total=Sum("cost"))
)
innerq = cte.join(Cost, region=cte.col.year).with_cte(cte)...
(我的用例与你的有点不同)。请参阅
文档了解更多信息。