首页 > 解决方案 > Django ORM:如何对一个值进行分组并获取该组中最后一个元素的不同值

问题描述

我整个星期都在尝试解决这个问题,但我似乎无法找到解决方案。

基本上我想对 2 个值(用户和分配)进行分组,然后根据日期取最后一个元素并得到这些分数的总和。下面是问题的描述。

使用 Postgres,这可以通过使用 .distinct("value") 轻松解决,但不幸的是我不使用 Postgres。

任何帮助将非常感激!!

UserAnswer
- user
- assignment
- date
- answer
- score

所以我想对所有用户/分配组合进行分组。然后我想获得该组中每个最后一个元素的分数。所以基本上:

user_1, assignment_1, 2019, score 1
user_1, assignment_1, 2020, score 2 <- Take this one
user_2, assignment_1, 2020, score 1
user_2, assignment_1, 2021, score 2 <- Take this one

我最好的尝试是使用注释,但后来我没有分数值了:

UserAnswer.objects.filter(user=student, assignment__in=assignments)
    .values("user", "assignment")
    .annotate(latest_date=Max('date'))

标签: pythondjangoannotationsdjango-orm

解决方案


最后,我不得不使用原始查询而不是 django 的 ORM。

subquery2 = UserAnswer.objects.raw("\
        SELECT id, user_id, assignment_id, score, MAX(date) AS latest_date\
        FROM soforms_useranswer \
        GROUP BY user_id, assignment_id\
    ")

# the raw queryset from above raw query 
# is very similar to queryset you get from django ORM query. 
# The difference is now we add 'id' and 'score' to the fields, 
# so later we can retrieve them, like below.

    sum2= 0
    for obj in subquery2:
        print(obj.score)
        sum2 += obj.score

    print('sum2 is')
    print(sum2)

在这里,我假设 user 和 assignment 都是外键。下面是一些东西:

class Assignment(models.Model):
    name = models.CharField(max_length=50)

class UserAnswer(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='answers')
    assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
    #assignment = models.CharField(max_length=200)
    score = models.IntegerField()
    date = models.DateTimeField(default=timezone.now)

推荐阅读