在跨越多个表的Django查询中聚合表达式

时间:2013-03-16 19:24:22

标签: aggregate-functions django-orm table-relationships

是否可以在Django ORM查询中计算相关表中字段的表达式(例如:减法)的聚合(例如:和)?

有关我正在尝试实现的完整示例,请参阅此工作SQL Fiddle。我将其分解为两个问题(other one here)。在这种情况下,我有一个代表一系列数字的模型Sequence,以及一个代表此序列中“链接”的模型Part

Sequence   Sequence   Sequence   Sequence   ...
0          5          20         15         ...
|-- Part --|-- Part --|-- Part --|-- ...

因此,每个Part代表 delta ,这是序列中两个值之间的差异。我有一组(非连续的)部分,想要计算这些增量的总和。像这样:

sum([p.after.value - p.before.value for p in Part.objects.filter(...)])

但是在一个查询中(原因是我想将它用作更复杂的子查询)。在SQL中很容易做到:

select sum(a.value - b.value)
  from part p
    join sequence a on p.after_id = a.id
    join sequence b on p.before_id = b.id
  where condition
  group by p.other_field;

我不知道如何使用Django ORM来做到这一点。我可以为一个值做到这一点:

Part.objects.filter(condition).aggregate(Sum('before__value')).values()

但不是涉及多个值的表达式。使用F() is not supported yet,所以我正在寻找另一种方法。我还查看了this question,它也是关于聚合中的表达式,但the accepted answer(使用extra)不适用于我的案例AFAIK,因为我感兴趣的字段不是在同一张表中,但在相关的表中。

>>> Part.objects.filter(condition).extra(select={
...     'delta':'sum(after__value - before__value)'
... })

DatabaseError: no such column: after__value

这是一个SSCCE,如果有人想要试验它:DownloadBrowse。它与上面链接的SQL fiddle具有相同的模型和数据。

1 个答案:

答案 0 :(得分:0)

现在1.8实施support for F expressions in aggregate,答案变得简单明了:

Part.objects.filter(condition).aggregate(sum=Sum(F('after__value')-F('before__value'))).values()