我试图构建以下类似于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)