【问题标题】:Django ORM more than one row returned by a subquery used as an expression用作表达式的子查询返回的 Django ORM 多于一行
【发布时间】:2021-05-17 10:03:03
【问题描述】:

我的子查询在不同的机器上表现不同。 子查询如下:

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

【问题讨论】:

  • "object_sale"."price" 在 group by 和 order by 中来自哪里?
  • 来自order_by
  • 但是我在查询集上没有看到任何order_by 调用?还是默认排序?
  • 是的,它来自模型的默认排序

标签: python django django-orm


【解决方案1】:

正如我们在查询中看到的,这部分是什么问题:

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")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    • 2018-02-13
    相关资源
    最近更新 更多