如何在Django QuerySets上减去两个带注释的列?

28

我需要对两个注释列的聚合结果进行排序。

所以我想做类似于这样的事情:

c = c.annotate(metric=Sum('results__metric'))
c = c.annotate(metric_prior=Sum('results__metric_prior'))
c = c.annotate(variance=F('metric')-F('metric_prior')) #doesn't work, for demonstrative purposes only

然后:

c = c.order_by('variance')

有没有人知道如何实现类似上述的功能?

3
我认为Django ORM的弯曲度有限,但我会点赞你的问题,看看是否有人能把它使用得更加广泛。我的建议是,要么亲自尝试使用原始SQL语句,要么使用更强大的ORM框架,例如SQLAlchemy(你可以在Django ORM中与之一同使用,参见SQLSoup)。 - Paulo Scardine
3
这个功能即将被添加到 Django 的未来版本中。https://github.com/django/django/pull/2496 - Anentropic
2个回答

21

实际上,

c = c.annotate(variance=F('metric')-F('metric_prior'))

使用 F 与注释,Django 1.8 开始支持 查询表达式、条件表达式和数据库函数

此外,您还可以按照表达式排序,只需要使用:

c = c.order_by(F('metric') - F('metric_prior'))

甚至只需要:

c = c.order_by(Sum('results__metric') - Sum('results__metric_prior'))

2

这里有一个4年之久的问题(截至2014年),但是可以通过一些简单的.extra()查询实现,就像这样:

items = MyModel.objects.extra(
    select = {'variance': 'SUM(relatedModel__someField) - SUM(relatedModel__someField)'},
)

是的,使用不同的数据库管理系统可能会有些不可预测性。但是,如果你将extra中的语法限制在非常普通的SQL范围内,它应该可以在几乎所有地方工作。


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