Нахождение общего балла из максимального балла конкретного пользователя в django orm
У меня есть функция, которая получает два параметра (contest_id, user_id), как я могу получить максимальную оценку каждой задачи в данном конкурсе для данного пользователя и затем суммировать все эти максимальные оценки? каждая задача может иметь ноль или много представленных оценок.
например: (problem_id,submitted_score) --> (1, 80), (1, 100), (2, 150), (2, 200), (3, 220), (3, 300)
Ожидаемый результат для этого примера должен быть 600, 100 + 200 + 300.
Модели:
class Contest(models.Model):
name = models.CharField(max_length=50)
holder = models.ForeignKey(User, on_delete=models.CASCADE)
start_time = models.DateTimeField()
finish_time = models.DateTimeField()
is_monetary = models.BooleanField(default=False)
price = models.PositiveIntegerField(default=0)
problems = models.ManyToManyField(Problem)
authors = models.ManyToManyField(User, related_name='authors')
participants = models.ManyToManyField(User, related_name='participants')
class Problem(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=1000)
writer = models.ForeignKey(User, on_delete=models.DO_NOTHING)
score = models.PositiveIntegerField(default=100)
class Submission(models.Model):
submitted_time = models.DateTimeField()
participant = models.ForeignKey(User, related_name="submissions", on_delete=models.DO_NOTHING)
problem = models.ForeignKey(Problem, related_name="submissions", on_delete=models.CASCADE)
code = models.URLField(max_length=200)
score = models.PositiveIntegerField(default=0)
Вы можете аннотировать Problem
s максимальным score
из связанных Submission
s, а затем суммировать их, так:
from django.db.models import Max, Sum
Problem.objects.filter(
contest__id=contest_id,
submissions__participant_id=user_id
).annotate(
max_score=Max('submissions__score')
).aggregate(
total=Sum('max_score')
)
В результате будет получен запрос, который выглядит следующим образом:
SELECT SUM(max_score)
FROM (
SELECT MAX(submission.score) AS max_score
FROM problem
INNER JOIN contest_problems ON problem.id = contest_problems.problem_id
INNER JOIN submission ON problem.id = submission.problem_id
WHERE contest_problems.contest_id = contest_id
AND submission.participant_id = 1
GROUP BY problem.id
) subquery
Если для любого Submission
для данного контекста не существует связанных Problem
, то вместо NULL
будет возвращено None
/0
.