Django ORM: Получение максимального значения поля с соответствующими значениями других полей

Django ORM: Получение максимального значения поля с соответствующими значениями других полей.

У меня есть эта таблица ( Счетчики): enter image description here

Я хочу получить конкретное date_time значение максимального traffic (которое рассчитывается на основе полей tftralacc, tfnscan, thtralacc и thnscan) для каждого cell_id.

Мне удалось получить это максимальное значение для каждого cell_id с помощью функций annotate() и group_by() API QuerySet в Django:

result = Counters.objects.filter(
    date_time__gte = date_start,
    date_time__lte = date_end
).annotate(
    # calculate the traffic for each row.
    traffic = Case(
        When(Q(tfnscan=0) or Q(thnscan=0), then=0),
        default = Round((F('tftralacc')*1.0/F('tfnscan')) + 
                        (F('thtralacc')*1.0/F('thnscan')), 2),
        output_field=FloatField()
    )
).order_by('cell_id').values(
    # Group by cell_id.
    'cell_id'
).order_by().annotate(
    # calculate the max traffic for the grouped Cells.
    max_traffic = Max('traffic')
)

Здесь демонстрируется рассчитанный трафик для каждого даты_времени: enter image description here

Мой код успешно возвращает максимальный трафик для каждого cell_id:

cell_id max_traffic
13997 3.92
14000 4.59

Но моя цель - получить соответствующее значение date_time для каждого максимального значения. примерно так:

cell_id max_traffic date_time
13997 3.92 2022-02-22 11:00:00+01
14000 4.59 2022-02-22 10:00:00+01

или

cell_id date_time
13997 2022-02-22 11:00:00+01
14000 2022-02-22 10:00:00+01

Потому что это максимальное значение является лишь средством для получения даты_времени, а не целью.

Примечание: Есть вопрос, который описывает мою проблему, но его ответ относится к обходному решению, которое невозможно для моей проблемы. SO Question

Используйте models.Subquery с models.OuterRef для объединения полей cell_id и traffic и используйте queryset.values() для выбора только date_time столбца.

counters_with_traffic = Counters.objects.filter(
    date_time__gte = date_start,
    date_time__lte = date_end
).annotate(
    # calculate the traffic for each row.
    traffic = Case(
        When(Q(tfnscan=0) or Q(thnscan=0), then=0),
        default = Round((F('tftralacc')*1.0/F('tfnscan')) + 
                        (F('thtralacc')*1.0/F('thnscan')), 2),
        output_field=FloatField()
    )
)

counters_date_time = counters_with_traffic.filter(
    cell_id=models.OuterRef('cell_id'),
    traffic=modesl.OuterRef('max_traffic'),
).values('date_time')

result = counters_with_traffic.order_by('cell_id').values(
    # Group by cell_id.
    'cell_id'
).order_by().annotate(
    # calculate the max traffic for the grouped Cells.
    max_traffic = Max('traffic'),
    date_time=models.Subquery(counters_date_time),    
)
Вернуться на верх