如何在 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))的主要内容,如果未能解决你的问题,请参考以下文章

P4213 模板杜教筛(Sum) min_25筛

Django学习路17_聚合函数(Avg平均值,Count数量,Max最大,Min最小,Sum求和)基本使用

Django学习路17_聚合函数(Avg平均值,Count数量,Max最大,Min最小,Sum求和)基本使用

[BZOJ1257][CQOI2007]余数之和sum 数学+分块

django功能六

django功能六