这是一个前沿功能,我目前正在使用它并很快就流血了。我想将子查询聚合注释到现有查询集上。在 1.11 之前执行此操作意味着自定义 SQL 或锤击数据库。这是 this 的文档,以及其中的示例:
from django.db.models import OuterRef, Subquery, Sum
comments = Comment.objects.filter(post=OuterRef('pk')).values('post')
total_comments = comments.annotate(total=Sum('length')).values('total')
Post.objects.filter(length__gt=Subquery(total_comments))
他们在汇总上进行注释,这对我来说似乎很奇怪,但无论如何。
我正在为此苦苦挣扎,所以我将其直接还原为我拥有数据的最简单的真实示例。我有Carpark
包含许多Space
s 的 s。如果这让你更快乐,请使用Book→Author
,但 - 现在 - 我只想使用Subquery
* 来注释相关模型的计数。
spaces = Space.objects.filter(carpark=OuterRef('pk')).values('carpark')
count_spaces = spaces.annotate(c=Count('*')).values('c')
Carpark.objects.annotate(space_count=Subquery(count_spaces))
这给了我一个可爱的印象ProgrammingError: more than one row returned by a subquery used as an expression
,在我的脑海中,这个错误非常有意义。子查询返回带有注释总数的空格列表。
这个例子表明某种魔法会发生,我最终会得到一个可以使用的数字。但这不是在这里发生的吗?如何注释聚合子查询数据?
嗯,我的查询的 SQL 中添加了一些东西……
我建立了一个新的停车场/空间模型并且它工作。所以下一步是找出是什么毒害了我的 SQL。在 Laurent 的建议下,我查看了 SQL 并试图使其更像他们在答案中发布的版本。这就是我发现真正问题的地方:
SELECT "bookings_carpark".*, (SELECT COUNT(U0."id") AS "c"
FROM "bookings_space" U0
WHERE U0."carpark_id" = ("bookings_carpark"."id")
GROUP BY U0."carpark_id", U0."space"
)
AS "space_count" FROM "bookings_carpark";
我已经突出显示了它,但它是那个子查询的GROUP BY ... U0."space"
. 出于某种原因,它正在重新调整两者。调查仍在继续。
编辑 2:好的,只要查看子查询 SQL,我就可以通过 ☹</p> 看到第二组
In [12]: print(Space.objects_standard.filter().values('carpark').annotate(c=Count('*')).values('c').query)
SELECT COUNT(*) AS "c" FROM "bookings_space" GROUP BY "bookings_space"."carpark_id", "bookings_space"."space" ORDER BY "bookings_space"."carpark_id" ASC, "bookings_space"."space" ASC
编辑3:好的!这两种模型都有排序顺序。这些正在执行到子查询。正是这些订单使我的查询膨胀并破坏了它。
我想这可能是 Django 中的一个错误,但没有在这两个模型上删除 Meta-order_by,有什么方法可以在查询时取消对查询的排序?
*我知道我可以为这个例子添加一个 Count 注释。我使用它的真正目的是一个更复杂的过滤器计数,但我什至无法让它工作。