在Django ORM中,计算grouped by查询上带注释字段的和的最大值?

2024-10-02 08:20:41 发布

您现在位置:Python中文网/ 问答频道 /正文

为了简单起见,我有四个表(A,B,Category和relationship),关系表将A的Intensity存储在B中,Category存储B的类型

A <--- Relation ---> B ---> Category

(所以A和B之间的关系是n对n,当B和类别之间的关系是n对1时)

我需要一个ORM按Category和A对关系记录进行分组,然后在每个(Category,A)中计算IntensitySum(在这里似乎很简单),然后我要注释每个类别中计算的Sum的最大值。在

我的代码类似于:

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

这会引发错误:

^{pr2}$

Django-group-by包有相同的错误。在

更多信息请参见this stackoverflow question。在

我使用的是Django 2和PostgreSQL。在

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

更新

经过一番挣扎,我发现我写的确实是一个聚合,但是我想要的是找出每个类别中每个A的AcSum的最大值。所以我想在计算完AcSum之后,我必须再次根据结果分组。基于这个观点,我发现了一个stack-overflow question,它提出了相同的概念(这个问题是在1年2个月前提出的,没有得到任何公认的答案)。 将另一个值('id')链接到集合既不能作为分组依据,也不能作为输出属性的过滤器,它会从集合中移除AcSum。由于分组依据结果集中的更改,向values()添加AcSum也不是一个选项。 我想我要做的是根据列中的字段(即id)对grouped by查询进行重新分组。 有什么想法吗?在


Tags: djangoidby关系错误orm类别values
2条回答

像这样的事情应该对你有用。我自己无法测试,请告诉我结果:

Relation.objects.annotate(
   b_category=F('B__Category')
).values(
   'A', 'b_category'
).annotate(
   SumInensityPerCategory=Sum('Intensity')
).values(
   'A', MaxIntensitySumPerCategory=Max('SumInensityPerCategory')
)

不能对聚合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:

^{pr2}$

通过使用array_agg(Postgres)或GroupConcat(MySQL)等后端特定功能来收集关系.ids在外部查询中组合在一起的。我不知道你在用什么。在

相关问题 更多 >

    热门问题