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

Я хочу получить конкретное 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')
)
Здесь демонстрируется рассчитанный трафик для каждого даты_времени:

Мой код успешно возвращает максимальный трафик для каждого 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),
)