【问题标题】:How to find Min(Sum(annotated column)) in Django如何在 Django 中找到 Min(Sum(annotated column))
【发布时间】: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 新手,我不确定如何使用子查询或存在来获得此结果。任何帮助将不胜感激

【问题讨论】:

    标签: python django orm psql


    【解决方案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')
    

    【讨论】:

    • 是的,我后来知道了。不过,感谢您的投入。
    猜你喜欢
    • 2021-12-30
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    相关资源
    最近更新 更多