如何在 Django 中找到 Min(Sum(annotated column))
Posted
技术标签:
【中文标题】如何在 Django 中找到 Min(Sum(annotated column))【英文标题】:How to find Min(Sum(annotated column)) in Django 【发布时间】:2021-01-11 18:44:27 【问题描述】:我有四个表 A、B、C 和 D。每个表通过 id 列以 A -> B -> C -> D 的方式关联。 例如。 A.id = B.a_id,B.id = C.b_id 和 C.id = D.c_id
我正在努力实现这样的目标
SELECT x.id, min(x.total) as mintotal FROM (SELECT "A"."id",
SUM(("D"."amount" * "D"."quantity")) AS "total", "C"."id" AS "qid"
FROM "A" LEFT OUTER JOIN "B" ON ("A"."id" = "B"."a_id") LEFT OUTER
JOIN "C" ON ("B"."id" = "C"."c_id") LEFT OUTER JOIN "D" ON ("C"."id"
= "D"."c_id") GROUP BY "A"."id", "C"."id") as x group by x.id ORDER BY mintotal ASC
我的等效 django 代码
query1 = (
A.objects.all().annotate(
qid=models.F('b__c__id'),
total=Sum(models.ExpressionWrapper(
models.F('b__c__d__amount')*models.F('b__c__d__quantity'),
output_field=models.DecimalField()
))
).order_by('total')
)
它给了我内部查询输出,但是当我再次尝试选择 id 和 Min(total) 时,它会抛出错误 -
FieldError: Cannot compute Min('total'): 'total' is an aggregate
我是 Django 新手,我不确定如何使用子查询或存在来获得此结果。任何帮助将不胜感激
【问题讨论】:
【参考方案1】:看起来这个SQL和你想要的一样
SELECT
A.id,
(
SELECT
Sum(D.amount * D.quantity)
FROM
D
JOIN
C ON C.id = D.c_id
JOIN
B ON B.id = C.b_id
WHERE
B.a_id = A.id
GROUP BY C.id
ORDER BY Sum(D.amount * D.quantity) ASC
LIMIT 1
) as mintotal
FROM
A;
这可以使用 Django 的子查询来完成
from django.db.models import Subquery, OuterRef, F
subquery = Subquery(D.objects.values(c__id)
.annotate(total=Sum(F('amount') * F('quantity')))
.filter(c__b__a__id=OuterRef('id'))
.order_by('total')
.values('total')[:1])
query1 = A.objects.annotate(mintotal=subquery)
# And if you really just want the A.id and mintotal columns:
query1 = A.objects.annotate(mintotal=subquery).values('id', 'mintotal')
【讨论】:
是的,我后来知道了。不过,感谢您的投入。以上是关于如何在 Django 中找到 Min(Sum(annotated column))的主要内容,如果未能解决你的问题,请参考以下文章
Django学习路17_聚合函数(Avg平均值,Count数量,Max最大,Min最小,Sum求和)基本使用
Django学习路17_聚合函数(Avg平均值,Count数量,Max最大,Min最小,Sum求和)基本使用