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

时间:2018-07-27 13:24:12

标签: django django-models

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

我这样做如下:

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 个答案:

答案 0 :(得分:4)

效率低下很可能是由于您对每一列都执行了查询。结果是有20个字段,您将执行20个查询。

进行查询通常很昂贵,并且从某种意义上来说,大量类型是“独立于查询”的,这与查询本身应该做什么无关:需要创建查询,然后将其传递给数据库,那么数据库需要提出一个“查询执行计划”,然后执行查询,并将响应传达回去。尽管查询本身当然会花费一些时间,但是您可以看到 per 查询也需要运行其他一些任务。因此,即使查询非常便宜,它们也会消耗大量资源。但是,如果过滤也不是一件简单的事情(不是很容易用索引解决的事情),我们还将做很多重复的工作来确定要考虑表的哪些行。

您可以先使用 list comprehension ,然后将其作为*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,以避免造成混淆以后。