获取Django查询集中所有字段的总和

3

我正在尝试对查询集中的字段求和。基本上,我想要每个字段的总和。

我是按照以下方式进行的:

field_names = MyModel._meta.get_fields()
queryset = MyModel.objects.filter(some filter criteria)

for fn in field_names:
    result = queryset.aggregate(Sum(fn.name))
    actual = result[fn.name+'__sum']

这显然是非常低效的。我该如何高效地做到这一点?
1个回答

6
效率低下可能是因为每个列都执行了一次查询。因此,对于20个字段,您执行了20个查询。
进行查询通常是昂贵的,并且大量的时间是“与查询无关”的,这意味着它需要时间,而不管查询本身的目的是什么:需要创建查询,将其传递给数据库,然后数据库需要提出“查询执行计划”,然后执行查询并将响应返回。尽管当然查询本身需要一些时间,但正如您所看到的,还有其他任务需要运行,每次查询都要运行。因此,即使查询非常便宜,它们也会消耗相当多的资源。如果筛选也不容易(不能轻松使用索引解决),那么我们还需要做很多重复工作来确定要考虑哪些表格行。
您可以通过首先使用列表推导式,然后将其作为* args传递来在一个聚合中完成所有操作。
result = queryset.aggregate(<b>*[</b>Sum(fn.name)<b> for fn in field_names]</b>)

现在,result是一个字典,将这些字段映射到它们对应的总和,类似于:
#  example result
result == { 'foo__sum': 42, 'bar__sum': 14, 'qux__sum': 52 }

查询语句如下:
SELECT SUM(foo) AS foo__sum, SUM(bar) AS bar__sum, SUM(qux) AS qux__sum
FROM mymodel
WHERE 1 = 1  -- some filter conditions

因此,所有聚合都在同一查询中计算。

注意:由于field_names是字段的集合而不是字段的名称,我建议将此变量重命名为fields,以避免后期引起任何混淆。


1
感谢您的建议,我已经根据建议修改了“field_names”。 - HenryM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接