集計の集計を行うことはできません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
Subquery
で結合を削除する方がパフォーマンスが高い場合があります array_agg
などのバックエンド固有の機能を使用する (Postgres)またはGroupConcat
(MySQL)Relation.ids
を収集します これらは外部クエリでグループ化されます。ただし、使用しているバックエンドはわかりません。