Django ORM,通过查询求和列值

Posted

技术标签:

【中文标题】Django ORM,通过查询求和列值【英文标题】:Django ORM, Sum column values through query 【发布时间】:2021-12-20 13:08:42 【问题描述】:

我有一个包含以下值的表:

user amount date
John 10 2017-07-01
John 20 2019-07-01
John 30 2020-09-01
John 40 2021-11-01
... ... ...
Dan -20 2019-02-01
Dan -30 2020-04-01
Dan -40 2021-06-01

函数的输入是一个日期范围,例如如下:

date_start = '2019-01-01'
date_end = '2021-11-07'

预期输出:

对于所有用户,对于这个日期范围内的每个日期,我想返回 amountssum,从当前日期到所有以前的日期,如下所示:

user amount date
John 30 (10+20) 2019-07-01
John 60 (10+20+30) 2020-09-01
John 100 (10+20+30+40) 2021-11-01
... ... ...
Dan -20 2019-02-01
Dan -50 (-20-30) 2020-04-01
Dan -90 (-20-30-40) 2021-06-01

我的努力

def get_sum_amount(self, date_start=None, date_end=None):
    date_detail = 
    # Minimum date
    if date_start:
        date_detail['date__gt'] = date_start

    # Maximum date
    if date_end:
        date_detail['date__lt'] = date_end

    detail = Financial.objects.filter(Q(**date_detail)) \
        .values('user') \
        .annotate(sum_amount=Coalesce(Sum(F('amount')), Value(0)))

但没有结果。

更新

上例的函数输出为:

user amount
John 100
Dan -90

【问题讨论】:

打印后能把输出贴在这里吗?? detail = Financial.objects.filter(Q(**date_detail)) \ .values('user') \ .annotate(sum_amount=Sum('amount'))) 我看到输出是正确的,对吗? @MohamedBeltagy 不,就像预期的输出一样,它应该返回,例如 John 的另外两个日期,其值为 30 和 60。 这种情况下最好去shell手动写表达式查看输出 【参考方案1】:

您可以使用带有user 分区的Window 函数来计算每个用户的累积总和,按日期排序:

detail = Financial.objects.filter(**date_detail).annotate(
    running_amount=Window(
        expression=Sum('amount'),
        partition_by=[F('user')],
        order_by=F('date').asc(),
    )
)

【讨论】:

以上是关于Django ORM,通过查询求和列值的主要内容,如果未能解决你的问题,请参考以下文章

Django:分组然后通过查询计算列值的总和

通过 orm 的 django 子查询

Django ORM - 通过模型查询多对多?

有没有办法通过 Django ORM 查询修改日期时间对象?

Django ORM - 通过多个相关对象和 Q 查询选择

django中的orm中怎么对筛选结果去重