gpt4 book ai didi

python - Django:在可变数量的列上注释总和

转载 作者:行者123 更新时间:2023-11-30 22:05:00 25 4
gpt4 key购买 nike

所以我阅读了注释列,并利用了 F() 函数,我看到了 this post关于如何对多列求和。但是,我正在使用 EAV 样式数据库,因此我得到了一个可变的列列表。考虑这个例子:

class TestModel(models.Model):
column_a = models.FloatField()
column_b = models.FloatField()
column_c = models.FloatField()
column_d = models.FloatField()

尝试 1:

columns = {'column_a', 'column_c', 'column_d'}
queryset = DummyModel.objects.annotate(total=Sum([F(column_name) for column_name in columns]))

但是,print(queryset.query)会产生错误django.core.exceptions.FieldError:无法解析表达式类型,未知的output_field

尝试 2:

queryset = DummyModel.objects.annotate(total=ExpressionWrapper(Sum([F(column_name) for column_name in columns]), output_field=FloatField())) 

这不会产生编译错误,但 SQL 查询会产生:

SELECT "test_model"."column_a", "test_model"."column_c", "test_model"."column_d", SUM([]) AS "total" FROM "test_model"

这是空的。有谁知道如何解决这个问题?非常感谢任何帮助!

最佳答案

要弄清楚这一点,首先想象一下表格会有所帮助:

column_a | column b | column_c
---------+----------+----------
1 | 2 | 3
4 | 5 | 6
7 | 8 | 9

Sum 是“垂直”运算;也就是说,如果我们想要 column_a 的总和,我们可以这样做

>>> DummyModel.objects.aggregate(total=Sum('column_a'))
{'total': 12}

如您所见,这将返回 1 + 4 + 7 == 12 ——因此您可以明白为什么我将其称为“垂直”总和。请注意,我们使用 aggregate 而不是 annotate:aggregate 用于垂直运算符。

如果我们想要“水平”总和(一行中的总和),我们将使用 F()+。因此,要在每一行中获取column_a + column_b,我们将使用

>>> DummyModel.objects.annotate(total=F('column_a') + F('column_b')).values('total')
<QuerySet [{'total': 3}, {'total': 9}, {'total': 15}]>

希望您能明白为什么我将其称为“水平”总和:我们在每一行中“水平”获得 ab 的总和。现在请注意,我们使用annotate,它用于水平操作。

如果事先不知道列的名称,则需要使用 functools.reduceoperator.add建立一个表达式:

>>> from functools import reduce
>>> from operator import add

>>> cols = ['column_b', 'column_c']
>>> expr = reduce(add, (F(col) for col in cols))
>>> DummyModel.objects.annotate(total=expr).values('total')
<QuerySet [{'total': 5}, {'total': 11}, {'total': 17}]>

如果我们想要同时水平和垂直总和——即column_a的总和加上column_b的总和——我们需要使用 SumF():

>>> DummyModel.objects.aggregate(total=Sum(F('column_a') + F('column_b')))
{'total': 27}

注意:聚合而不是注释,因为我们最终要进行垂直操作;行的Sum。是的,首先有一个水平运算,但由于我们最终是Sum,所以我们需要aggregate

所以,总而言之,如果字段是变量,我们需要结合 aggregateSumreduce 技巧从上面:

>>> cols = ['column_b', 'column_c']
>>> expr = reduce(add, (F(col) for col in cols))
>>> DummyModel.objects.aggregate(total=Sum(expr))
{'total': 33}

希望这有帮助!

关于python - Django:在可变数量的列上注释总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53131762/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com