Python Django:在可变列数上注释sum
我已经阅读了注释列,并利用了F()函数,了解了如何对多个列求和。但是,我使用的是EAV样式的数据库,所以我得到了一个列的可变列表。考虑这个例子:Python Django:在可变列数上注释sum,python,django,django-annotate,Python,Django,Django Annotate,我已经阅读了注释列,并利用了F()函数,了解了如何对多个列求和。但是,我使用的是EAV样式的数据库,所以我得到了一个列的可变列表。考虑这个例子: class TestModel(models.Model): column_a = models.FloatField() column_b = models.FloatField() column_c = models.FloatField() column_d = models.FloatField() 尝试1:
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]))
queryset = DummyModel.objects.annotate(total=ExpressionWrapper(Sum([F(column_name) for column_name in columns]), output_field=FloatField()))
但是,print(queryset.query)
会产生错误django.core.exceptions.FieldError:无法解析表达式类型,未知输出\u字段
尝试2:
columns = {'column_a', 'column_c', 'column_d'}
queryset = DummyModel.objects.annotate(total=Sum([F(column_name) for column_name in columns]))
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
是一种“垂直”操作;也就是说,如果我们想要列a
的总和,我们可以这样做
>>> DummyModel.objects.aggregate(total=Sum('column_a'))
{'total': 12}
如您所见,这将返回1+4+7==12
——因此您可以理解为什么我将其称为“垂直”和。请注意,我们使用的是aggregate
而不是annotate
:aggregate
用于垂直运算符
相反,如果我们想要“水平”总和——一行中的总和——我们将使用F()
和+
。因此,要在每行中获得列a+列b
,我们将使用
>>> DummyModel.objects.annotate(total=F('column_a') + F('column_b')).values('total')
<QuerySet [{'total': 3}, {'total': 9}, {'total': 15}]>
如果我们想要一个水平和一个垂直的总和——即列a
的总和加上列b
的总和——我们需要使用和F()
:
注意:aggregate
而不是annotate,因为我们最终使用的是垂直操作;行的总和。是的,首先有一个水平操作,但是因为我们最终需要求和
,所以我们需要聚合
因此,总而言之,如果字段是一个变量,我们需要结合聚合
,求和
,以及上面的减少
技巧:
>>> cols = ['column_b', 'column_c']
>>> expr = reduce(add, (F(col) for col in cols))
>>> DummyModel.objects.aggregate(total=Sum(expr))
{'total': 33}
希望这有帮助 是的,这就是我要找的。实际上,我可以使用更简单的方法,甚至可以合法地使用python中的简单的sum
与F()
进行水平求和,以使其正常工作。使用reduce
将更为通用,但对于我的使用目的来说并非必需。在任何情况下,我都不需要聚合,只需要动态水平求和。原来我很接近。谢谢