2017-04-20 100 views
3

是否可以使用django的orm来计算累计(运行)总和?请看下面的模式:与django orm和postgresql的累计(运行)总和

class AModel(models.Model): 
    a_number = models.IntegerField() 

了一组数据,其中a_number = 1的。这样我在数据库中有一个数字(> 1)AModel实例全部使用a_number=1。我希望能够返回以下内容:

AModel.objects.annotate(cumsum=??).values('id', 'cumsum').order_by('id') 
>>> ({id: 1, cumsum: 1}, {id: 2, cumsum: 2}, ... {id: N, cumsum: N}) 

理想情况下,我希望能够限制/过滤累积总和。所以在上述情况下,我想限制结果cumsum <= 2

我相信在postgresql中可以使用窗口函数实现累计和。这是如何转换成ORM的?

+0

我不明白。什么是cumsum?并且只有一条记录的id = 1 –

+0

cumsum ==累计和,显然这是针对多个记录 - 编辑得更清楚,因此数据集的大小大于1。 – wrdeman

+0

我不认为你可以用ORM做它...用python代替 –

回答

2

从迪马Kudosh答案,并基于https://stackoverflow.com/a/5700744/2240489我必须做到以下几点: 我删除了参考的sql PARTITION BY中并获得ORDER BY更换

AModel.objects.annotate(
    cumsum=Func(
     Sum('a_number'), 
     template='%(expressions)s OVER (ORDER BY %(order_by)s)', 
     order_by="id" 
    ) 
).values('id', 'cumsum').order_by('id', 'cumsum') 

此给出以下。 sql:

SELECT "amodel"."id", 
SUM("amodel"."a_number") 
OVER (ORDER BY id) AS "cumsum" 
FROM "amodel" 
GROUP BY "amodel"."id" 
ORDER BY "amodel"."id" ASC, "cumsum" ASC 

Dima Kudosh的答案没有总结结果,但上面说到了。

0

入住这

AModel.objects.order_by("id").extra(select={"cumsum":'SELECT SUM(m.a_number) FROM table_name m WHERE m.id <= table_name.id'}).values('id', 'cumsum') 

其中table_name应该是表的数据库的名称。

1

您可以试着用Func expression来做到这一点。

from django.db.models import Func, Sum 

AModel.objects.annotate(cumsum=Func(Sum('a_number'), template='%(expressions)s OVER (PARTITION BY %(partition_by)s)', partition_by='id')).values('id', 'cumsum').order_by('id') 
+0

谢谢,真的很感谢你的回答。它不适合我,我发布了我的修正案。 – wrdeman