从Django Orm中所有用户的最高分数中查找平均分数

时间:2019-09-28 18:40:34

标签: django django-models

我正在尝试从所有完成的考试中计算平均分数。用户可以根据需要发送任意数量的考试。因此,完成考试的数据可以像...

(用户,完成考试的分数)

(1,8),(1,9),(1,10),(2,2),(2,3),(3,8)

我想要每个用户的所有最高分的平均分。

上述数据的预期平均得分应为7。“(10 + 3 + 8)/ 3”

我的Django模型

class Exam(models.Model):
    title = models.TextField("Title")
    description = models.TextField("Description")

class Question(models.Model):
    exam_id = models.ForeignKey("Exam", on_delete=models.CASCADE)
    title = models.CharField(max_length=500, verbose_name="Question")
    score = models.FloatField(default=1)

class Answer(models.Model):
    question_id = models.ForeignKey("Question", on_delete=models.CASCADE)
    title = models.CharField(max_length=500, verbose_name="Answer")

class FinishedExam(models.Model):
    exam = models.ForeignKey("Exam", on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    total_score = models.FloatField(default=0)

1 个答案:

答案 0 :(得分:1)

我们可以为每次使用首先注释最大分数,然后在该集合上进行汇总:

from django.db.models import Avg, Max

User.objects.annotate(
    max_score=Max('finishedexam__score')
).aggregate(
    avg_score=Avg('max_score')
)['avg_score']

这将产生如下查询:

SELECT AVG(max_score)
FROM (
    SELECT auth_user.id AS Col1, MAX(core_finishedexam.score) AS max_score
    FROM auth_user
    LEFT OUTER JOIN core_finishedexam ON auth_user.id = core_finishedexam.user_id
    GROUP BY auth_user.id ORDER BY NULL
) subquery

子查询将因此生成每个用户的最高分数,然后我们计算平均值。

如果要针对特定​​考试进行过滤,可以使用以下方法进行过滤:

from django.db.models import Avg, Max

User.objects.filter(
    finishedexam__exam=my_exam
).annotate(
    max_score=Max('finishedexam__score')
).aggregate(
    avg_score=Avg('max_score')
)['avg_score']

这将仅取参加该考试的用户的平均值(至少一次)。因此,从未使用过 my_exam 的用户将被忽略。