首页 > 解决方案 > Django ORM分别查询正负值的总和

问题描述

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

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

尝试使用 Case 和 When,但无法理解在“then”子句中放入什么内容。

看到这个答案相关,但我想避免“额外”。- ' Django 查询集 SUM 正负值'

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

标签: djangopython-3.xdjango-orm

解决方案


具有三个聚合的过程

你可以使用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(值大于零)或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']

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


推荐阅读