Выберите самое быстрое время для каждого спортсмена - PullRequest
1 голос
/ 09 мая 2019

Я пытаюсь составить список лучших результатов каждого спортсмена, упорядоченных по времени.

В настоящее время я просто выбрасываю каждый дубликат результата после получения всех результатов и своевременного упорядочения.

У меня есть две следующие модели:

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 голосов
/ 09 мая 2019

Вы можете использовать для этого аннотацию, например:

from django.db.models import <b>Min</b>

Athlete.objects.annotate(
    <b>time=Min('result__time')</b>
).order_by(<b>'time'</b>)

Объекты Athlete, которые возникают из этого набора запросов, будут иметь дополнительный атрибут .time с минимальным time из связанных Result объектов. Кроме того, мы используем .order_by(..), чтобы затем упорядочить результаты по аннотации time.

Django обработает это запросом, похожим на:

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

В случае, если Athlete не имеет связанных Result s, его time будет None.

В случае, если есть Athlete без связанных результатов и Athlete s со связанными результатами, это зависит от базы данных, где будет упорядочен NULL s (до значений со значениями или после значений с ценности). Вы можете решить это, указав, как сделать заказ с помощью NULL s, используя nulls_first или nulls_last [Django-doc] в F выражение. Например:

from django.db.models import <b>F</b>, Min

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

это будет порядок Athlete с без результатов в конце QuerySet.

...