用作表达式的子查询返回的 Django ORM 多行
Django ORM more than one row returned by a subquery used as an expression
我的子查询在不同的机器上表现不同。
子查询看起来像:
Sale.objects.filter(object_id=OuterRef("id"), is_canceled=False)
.values("object")
.annotate(total_amount=Coalesce(Sum("amount"), 0))
.values("total_amount")
在我的本地机器上我有 3 个 Sale 实例,查询结果是:
<QuerySet [{'object': 1, 'total_amount': 210}]>
在我的开发机器上,我有 2 个 Sale 实例,调用的结果如下所示:
<QuerySet [{'object': 100, 'total_amount': 20}, {'object': 100, 'total_amount': 10}]>
我检查了 Django ORM 在这两种情况下生成的查询,它看起来是一样的
SELECT "object_sale"."object_id", COALESCE(SUM("object_sale"."amount"), 0) AS "total_amount"
FROM "object_sale"
WHERE ("object_sale"."object_id" = 1)
GROUP BY "object_sale"."object_id", "object_sale"."price"
ORDER BY "object_sale"."price" ASC
我们在查询中可以看到这部分是什么问题:
GROUP BY "object_sale"."object_id", "object_sale"."price"
ORDER BY "object_sale"."price" ASC
不是简单地按 object_id
分组,而是按 price
分组,但这会导致结果中有多行,而且结果也不正确。因此我们不希望按 price
进行排序或分组。这是由模型的默认排序在 price
上引起的,为了解决这个问题,我们可以简单地在查询集上调用 order_by
而不使用任何参数来删除默认排序:
Sale.objects.filter(object_id=OuterRef("id"), is_canceled=False).order_by()
.values("object")
.annotate(total_amount=Coalesce(Sum("amount"), 0))
.values("total_amount")
我的子查询在不同的机器上表现不同。 子查询看起来像:
Sale.objects.filter(object_id=OuterRef("id"), is_canceled=False)
.values("object")
.annotate(total_amount=Coalesce(Sum("amount"), 0))
.values("total_amount")
在我的本地机器上我有 3 个 Sale 实例,查询结果是:
<QuerySet [{'object': 1, 'total_amount': 210}]>
在我的开发机器上,我有 2 个 Sale 实例,调用的结果如下所示:
<QuerySet [{'object': 100, 'total_amount': 20}, {'object': 100, 'total_amount': 10}]>
我检查了 Django ORM 在这两种情况下生成的查询,它看起来是一样的
SELECT "object_sale"."object_id", COALESCE(SUM("object_sale"."amount"), 0) AS "total_amount"
FROM "object_sale"
WHERE ("object_sale"."object_id" = 1)
GROUP BY "object_sale"."object_id", "object_sale"."price"
ORDER BY "object_sale"."price" ASC
我们在查询中可以看到这部分是什么问题:
GROUP BY "object_sale"."object_id", "object_sale"."price"
ORDER BY "object_sale"."price" ASC
不是简单地按 object_id
分组,而是按 price
分组,但这会导致结果中有多行,而且结果也不正确。因此我们不希望按 price
进行排序或分组。这是由模型的默认排序在 price
上引起的,为了解决这个问题,我们可以简单地在查询集上调用 order_by
而不使用任何参数来删除默认排序:
Sale.objects.filter(object_id=OuterRef("id"), is_canceled=False).order_by()
.values("object")
.annotate(total_amount=Coalesce(Sum("amount"), 0))
.values("total_amount")