与django orm和postgresql

时间:2017-04-20 11:11:35

标签: python django postgresql orm

是否可以使用django的orm来计算累积(运行)总和?考虑以下模型:

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

一组数据a_number = 1。这样我在数据库中有AModela_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

理想情况下,我希望能够限制/过滤累积总和。因此,在上述情况下,我想将结果限制为$sqlOverall = "SELECT CAST(AVG('scoreOverall') AS DECIMAL('10,1')) FROM 'ratings' WHERE gameID = '$id'"; $scoreOverall = mysqli_query($conn, $sqlOverall);

我相信在postgresql中可以使用窗口函数实现累积和。这怎么翻译成ORM?

5 个答案:

答案 0 :(得分:3)

作为参考,从Django 2.0开始,可以使用Window函数来实现此结果:

AModel.objects.annotate(cumsum=Window(Sum('a_number'), order_by=F('id').asc()))\
              .values('id', 'cumsum').order_by('id', 'cumsum')

答案 1 :(得分:2)

来自Dima 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的答案并非总结结果,但上述情况确实如此。

答案 2 :(得分:2)

对于后代,我发现这对我来说是一个很好的解决方案。我不需要将结果作为QuerySet,所以我可以负担得起,因为我只是要使用D3.js绘制数据:

import numpy as np
import datettime

today = datetime.datetime.date()

raw_data = MyModel.objects.filter('date'=today).values_list('a_number', flat=True)

cumsum = np.cumsum(raw_data)

答案 3 :(得分: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')

答案 4 :(得分: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应该是数据库中表的名称。