Django ORM如何在WHERE语句中执行聚合子查询?



我试图构建以下类似于Django ORM的查询:

SELECT * FROM table WHERE depth = (SELECT MIN(depth) FROM table)

如何用Django ORM符号来写?到目前为止,似乎很难使用这样的聚合,因为QuerySet.aggregate()不是惰性求值的,而是直接执行的。

我知道这个基本的例子可以写成Model.objects.filter(depth=Model.objects.aggregate(m=Min('depth'))['m']),但它不评估懒惰,需要2个单独的查询。对于更复杂的情况,我肯定需要一个延迟求值的查询集。


供参考,我尝试过的事情都失败了:

  • Model.objects.order_by().values().annotate(m=Min('depth').values('m'))的子查询将导致GROUP BY id看起来很难丢失。
  • Model.objects.annotate(m=Min('depth')).filter(depth=F('m'))的子查询将给出GROUP BY id,并在主要结果中包含m值,因为这就是annotation所做的。

我目前的解决方法是使用QuerySet.extra(where=[...]),但我更希望看到ORM生成该代码。

应该可以了

MyModel.objects.filter(
depth=MyModel.objects.annotate(min_depth=Min('depth)).values('min_depth')[:1]
)

使用annotate而不是aggregate将使查询集保持惰性。

根据@Brad的建议,这似乎是一个可行的选择:

MyModel.objects.filter(
depth=MyModel.objects.order_by('depth').values('depth')[:1]
)

变成了SQL:

SELECT * FROM table WHERE depth = (SELECT depth FROM table ORDER BY depth LIMIT 1)

最新更新