2017-04-20 80 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