Django ORM: SUM сгруппированных MAX
Я пытаюсь перевести этот SQL запрос:
SELECT user_id, SUM(max_score)
FROM (SELECT user_id, MAX(score) AS max_score
FROM submissions
GROUP BY exercise_id, user_id) AS subquery
GROUP BY user_id;
где таблица submissions
имеет столбцы user_id
, exercise_id
и score
.
Перевод внутреннего подзапроса приводит к:
subquery = (
Submission.objects
.values("exercise", "user")
.annotate(max_score=Max("score"))
.values("user", "max_score")
)
с таким набором запросов:
<QuerySet [{'user': 1, 'max_score': 27},
{'user': 2, 'max_score': 50},
{'user': 1, 'max_score': 16},
{'user': 3, 'max_score': 14},
{'user': 1, 'max_score': 14},
...]>
Однако, когда я пытаюсь суммировать их по пользователям, используя subquery.annotate(total_score=Sum("max_score"))
, я получаю:
FieldError: Cannot compute Sum('max_score'): 'max_score' is an aggregate
Как я могу реализовать это в Django ORM вместо неэффективного решения вроде этого:
scores = defaultdict(int)
for row in subquery:
scores[row['user']] += row['max_score']
result = subquery.aggregate(total_score=Sum("max_score"))
Для доступа к значению в результате:
result['total_score']
annotate
возвращает строки со специальным атрибутом, установленным на каждой строке, который вы указываете в аргументе метода, но он все равно возвращает строки (QuerySet). Метод aggregate
возвращает результат агрегации - одно значение.
Дайте мне знать, если это работает :)