微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算在Django ORM中按查询分组的带注释字段的总和最大值?

如何解决计算在Django ORM中按查询分组的带注释字段的总和最大值?

您无法进行汇总的汇总Max(Sum()),无论您是否使用ORM,它在sql中都是无效的。相反,您必须将表自身联接起来才能找到最大值。您可以使用子查询来执行此操作。下面的代码对我来说似乎很正确,但是请记住,我没有什么可以运行的,因此它可能并不完美。

from django.db.models import Subquery, OuterRef

annotation = {
    'AcSum': Sum('intensity')
}
# The basic query is on Relation grouped by A and Category, annotated
# with the Sum of intensity
query = Relation.objects.values('a', 'b__category').annotate(**annotation)

# The subquery is joined to the outerquery on the Category
sub_filter = Q(b__category=OuterRef('b__category'))
# The subquery is grouped by A and Category and annotated with the Sum
# of intensity, which is then ordered descending so that when a LIMIT 1
# is applied, you get the Max.
subquery = Relation.objects.filter(sub_filter).values('a', 'b__category').annotate(**annotation).order_by('-AcSum').values('AcSum')[:1]

query = query.annotate(max_intensity=Subquery(subquery))

这应该生成如下的sql

SELECT a_id, category_id,
       (SELECT SUM(U0.intensity) AS AcSum
        FROM RELATION U0
        JOIN B U1 on U0.b_id = U1.id
        WHERE U1.category_id = B.category_id
        GROUP BY U0.a_id, U1.category_id
        ORDER BY SUM(U0.intensity) DESC
        LIMIT 1
       ) AS max_intensity
FROM Relation
JOIN B on Relation.b_id = B.id
GROUP BY Relation.a_id, B.category_id

通过使用特定于后端的功能(例如array_agg(Postgres)或GroupConcat(MysqL))收集在外部查询中分组在一起的Relation.id,在子查询中消除联接可能会更有效。但是我不知道您正在使用什么后端。

解决方法

为简单起见,我有四个表(A,B,类别和关系),关系表将IntensityA的A存储在B中,类别存储B的类型。

A <-关系—> B->类别

(因此,当B和Category之间的关系为n到1时,A和B之间的关系为n到n)

我的类别和需要一个ORM到组关系的记录,然后计算出SumIntensity每个(A类,A)(似乎简单到这里),然后我要诠释的最大计算Sum每个类别。

我的代码是这样的:

 A.objects.values('B_id').annotate(AcSum=Sum(Intensity)).annotate(Max(AcSum))

引发错误:

django.core.exceptions.FieldError: Cannot compute Max('AcSum'): 'AcSum' is an aggregate

具有相同错误的Django-group-
by
软件包。

我正在使用Django 2和PostgreSQL。

有没有办法使用ORM来实现这一目标,如果没有,使用原始SQL表达式的解决方案是什么?

更新资料

经过大量的努力之后,我发现我写的确实是一个聚合,但是我想要的是找出每个类别中每个A的最大AcSum。所以我想我必须在AcSum计算之后再次对结果进行分组。基于这一见解,我发现了一个堆栈溢出问题,该问题提出了相同的概念(该问题是在1年零2个月前提出的,没有任何可接受的答案)。将另一个值(’id’)链接到集合既不能用作group_by,也不能用作输出属性的过滤器,它会从集合中删除AcSum。由于按结果集分组的更改,因此也不可以将AcSum添加到values()。我认为我想做的是根据列(即id)中的字段对查询分组进行重新分组。有什么想法吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。