【问题标题】:Django ORM Query for Sum of positive and negative values SeparatelyDjango ORM分别查询正负值的总和
【发布时间】:2019-02-26 18:05:54
【问题描述】:

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    三个聚合的过程

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

    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__gt=0(值大于零)或value__lt=0(值小于零)的行传递'value' 值。

    这将产生一个包含三个键的字典,例如:

    # 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']

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

    【讨论】:

    • 您的代码缺少一些逗号...。我无法让 output_field 被接受? agg = SomeModel.objects.aggregate( total=Sum('value'), total_pos=Sum(Case( When(value__gt=0, then=F('value')), default=Value(0) )) )跨度>
    • @BenjaminSchollnick:谢谢,我已经添加了逗号。在您的情况下,value 使用什么字段?
    • 我正在使用一个名为 display_size 的字段,它是文件的大小。(-1 表示不存在)。因此,只想对正值求和... display_size = models.BigIntegerField(default=-1, db_index = True)
    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2019-03-26
    • 2020-01-26
    • 2015-08-15
    • 2020-12-03
    相关资源
    最近更新 更多