Nie możesz wykonać agregacji agregacji Max(Sum())
, nie obowiązuje w SQL, niezależnie od tego, czy używasz ORM, czy nie. Zamiast tego musisz dołączyć do stołu, aby znaleźć maksimum. Możesz to zrobić za pomocą podzapytania. Poniższy kod wydaje mi się odpowiedni, ale pamiętaj, że nie mam na czym go uruchomić, więc może nie być idealny.
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))
Powinno to wygenerować kod SQL, taki jak:
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
Bardziej wydajne może być wyeliminowanie sprzężenia w Subquery
za pomocą funkcji specyficznej dla backendu, takiej jak array_agg
(Postgres) lub GroupConcat
(MySQL) do zbierania Relation.ids
które są zgrupowane w zewnętrznym zapytaniu. Ale nie wiem, jakiego backendu używasz.