我正在尝试对查询集中的记录中的字段求和。我基本上想要每个字段的总和。
我这样做如下:
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']
这显然是非常低效的。如何有效地做到这一点?
答案 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
,以避免造成混淆以后。