首页 > 解决方案 > 获取 Django 查询集中所有字段的总和

问题描述

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

我这样做如下:

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

这显然是非常低效的。我如何有效地做到这一点?

标签: djangodjango-models

解决方案


效率低下可能是由于您对每一列都执行查询。作为 20 个字段的结果,您执行 20 个查询。

进行查询通常是昂贵的,并且大量类型是“独立于查询”的,因为它需要时间,无论查询本身应该做什么:需要创建查询,将其传递给数据库,然后数据库需要提出一个“查询执行计划”,然后执行查询,并将响应传回。当然,查询本身需要一些时间,但正如您所见,每个查询还需要运行其他一些任务。因此,即使查询非常便宜,它们也会消耗大量资源。但是,如果过滤也很重要(不是可以通过索引轻松解决的问题),我们还会做很多重复的工作来确定要考虑表的哪些行。

您可以通过首先使用列表理解,然后将其传递为*args

result = queryset.aggregate(*[Sum(fn.name) for fn in field_names])

现在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,以避免以后出现任何混淆。


推荐阅读