我正在尝试构建类似于 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
值,因为这就是注释所做的。我目前的解决方法是使用
QuerySet.extra(where=[...])
但我更愿意看到 ORM 生成该代码。
这应该有效
MyModel.objects.filter(
depth=MyModel.objects.annotate(min_depth=Min('depth)).values('min_depth')[:1]
)
使用注释而不是聚合将使查询集保持惰性。
根据@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)