Django ORM分别查询正负值的总和

时间:2018-09-22 16:51:21

标签: django python-3.x django-orm

我在数据库中有一列,我们称其为dummy_column。 它具有正值和负值。 我想计算所有正数的总和,以及所有负数的总和(正+负)的总和,即我想将输出分为3个单独的值。

使用Sum('dummy_column')可以计算两者的总和

尝试使用大小写和时间,但是不明白在'then'子句中要输入什么。

看到这个答案是相关的,但我想避免“多余”。 -'Django queryset SUM positive and negative values'

写代码没什么,所以没有。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

具有三个聚合的过程

您可以在Sum(..)上使用Case,例如:

from django.db.models import Case, F, IntegerField, Sum, Value, When

agg = SomeModel.objects.aggregate(
    total=Sum('value')
    total_pos=Sum(Case(
        When(value__gt=0, then=F('value'))
        default=Value(0)
        output_field=IntegerField()
    ))
    total_neg=Sum(Case(
        When(value__lt=0, then=F('value'))
        default=Value(0)
        output_field=IntegerField()
    ))
)

(使用SomeModel是我们要为其计算聚合的模型,以及value字段(这里是IntegerField,其中包含我们要求和的值)。

When(..)对象因此指定我们为'value'(该值大于零)或value__gt=0(该值小于1)的行传递value__lt=0值大于零)。

这将导致带有三个键的字典,例如:

# sample output
agg == {'total': 12, 'total_pos': 14, 'total_neg': -2}

然后,您可以获取以下值:

agg['total']  # 12

具有两个聚合的过程

因为我们知道agg['total'] == agg['total_pos'] + agg['total_neg'],所以我们只能计算元素的一个,并对字典进行后处理,例如:

from django.db.models import Case, F, IntegerField, Sum, Value, When

agg = SomeModel.objects.aggregate(
    total=Sum('value')
    total_pos=Sum(Case(
        When(value__gt=0, then=F('value'))
        default=Value(0)
        output_field=IntegerField()
    ))
)

agg['total_neg'] = agg['total'] - agg['total_pos']

这可能会更有效,因为我们避免额外检查每一行(尽管这取决于数据库如何建立索引等)。