为每个运动员选择最快的时间

时间:2019-05-09 18:09:24

标签: django django-models django-queryset django-postgresql

我正在尝试按时间顺序列出每位运动员的最佳成绩列表。

目前,我只是在获得所有结果并按时订购后扔掉所有重复的结果。

我有以下两种型号:

class Athlete(models.Model):
    name = models.CharField(max_length=100)

class Result(models.Model):
    athlete = ForeignKey(Athlete, on_delete=models.CASCADE)
    time = models.DurationField()

说结果表如下:

athlete         time   
-------         ----
1               15.00
1               14.00
2               16.00
2               18.00
2               13.00
3               12.00

如何为每个运动员获得最快的时间,然后按时对列表进行排序? 像这样:

athlete         time   
-------         ----
3               12.00
2               13.00
1               14.00

1 个答案:

答案 0 :(得分:0)

您可以为此使用注释,例如:

from django.db.models import Min

Athlete.objects.annotate(
    time=Min('result__time')
).order_by('time')

此查询集产生的Athlete对象将具有一个额外的属性.time,该属性具有 related time对象中的最小Result。我们还使用.order_by(..)通过time批注对结果进行排序。

Django将使用如下查询进行处理:

SELECT athlete.*, MIN(result.time) AS time
FROM athlete
LEFT OUTER JOIN bar ON athlete.id = result.athlete_id
GROUP BY athlete.*
ORDER BY time ASC

如果Athlete没有相关的Result,则其time将是None

如果有Athlete个没有相关结果,而Athlete个有相关结果,则取决于数据库将对NULL个进行排序的位置(在有值的情况之前) ,或在带有值的值之后)。您可以通过在NULL表达式中使用nulls_first or nulls_last [Django-doc]指定如何对F进行排序来解决该问题。例如:

from django.db.models import F, Min

Athlete.objects.annotate(
    time=Min('result__time')
).order_by(F('time').asc(nulls_last=True))

这将对Athlete进行排序,QuerySet末尾没有任何结果。