Django ORM:获取具有相应其他字段值的字段的最大值
Django ORM: Get maximum value of a field with corresponding other fields values
我有这个 Table(计数器):
cell_id
tftralacc
tfnscan
thtralacc
thnscan
date_time
13997
10
360
94
360
2022-02-22 00:00:00+01
13997
0
360
0
360
2022-02-22 01:00:00+01
13997
0
360
0
360
2022-02-22 02:00:00+01
13997
0
360
0
360
2022-02-22 03:00:00+01
13997
36
360
83
360
2022-02-22 04:00:00+01
13997
0
360
2
360
2022-02-22 05:00:00+01
13997
1
360
15
360
2022-02-22 06:00:00+01
13997
11
360
159
360
2022-02-22 07:00:00+01
13997
21
360
409
360
2022-02-22 08:00:00+01
13997
25
360
1282
360
2022-02-22 09:00:00+01
13997
20
360
1201
360
2022-02-22 10:00:00+01
13997
30
360
1381
360
2022-02-22 11:00:00+01
13997
42
360
924
360
2022-02-22 12:00:00+01
14000
1
360
36
360
2022-02-22 00:00:00+01
14000
0
360
0
360
2022-02-22 01:00:00+01
14000
1
360
0
360
2022-02-22 02:00:00+01
14000
0
360
2
360
2022-02-22 03:00:00+01
14000
0
360
0
360
2022-02-22 04:00:00+01
14000
0
360
12
360
2022-02-22 05:00:00+01
14000
3
360
4
360
2022-02-22 06:00:00+01
14000
24
360
123
360
2022-02-22 07:00:00+01
14000
31
360
374
360
2022-02-22 08:00:00+01
14000
18
360
620
360
2022-02-22 09:00:00+01
14000
38
360
1616
360
2022-02-22 10:00:00+01
14000
36
360
1410
360
2022-02-22 11:00:00+01
14000
24
360
957
360
2022-02-22 12:00:00+01
我想获取最大流量的具体date_time值(这是根据字段计算的tftralacc、tfnscan、thtralacc 和 thnscan)对于每个cell_id.
我已经设法通过使用 Django 的 QuerySet 的 annotate()
和 group_by()
函数为每个 cell_id 获得最大值API:
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')
)
为每个 date_time 计算的 流量 如下所示:
我的代码成功了returns每个最大流量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
因为最大值只是获得 date_time 的手段,而不是目标。
注意:有一个问题描述了我的问题,但它的答案是指一个变通解决方案,这对我的问题是不可能的。
使用 models.Subquery
with models.OuterRef
加入 cell_id
字段。然后用queryset.annotate()
注解子查询max_traffic
。最后,使用 queryset.filter()
到 select 具有 traffic
等于 max_traffic
的行,并使用 .distinct()
删除重复行。
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) | Q(thnscan=0), then=0),
default=Round((F('tftralacc') * 1.0 / F('tfnscan')) +
(F('thtralacc') * 1.0 / F('thnscan')), 2),
output_field=models.FloatField()
)
)
counters_with_max_traffic = 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'),
).filter(cell_id=models.OuterRef("cell_id")).values("max_traffic")
result = counters_with_traffic.annotate(
max_traffic=models.Subquery(counters_with_max_traffic),
).filter(
traffic=models.F("max_traffic")
).values(
"cell_id", "max_traffic", "date_time"
).distinct("cell_id", "max_traffic")
我有这个 Table(计数器):
cell_id | tftralacc | tfnscan | thtralacc | thnscan | date_time |
---|---|---|---|---|---|
13997 | 10 | 360 | 94 | 360 | 2022-02-22 00:00:00+01 |
13997 | 0 | 360 | 0 | 360 | 2022-02-22 01:00:00+01 |
13997 | 0 | 360 | 0 | 360 | 2022-02-22 02:00:00+01 |
13997 | 0 | 360 | 0 | 360 | 2022-02-22 03:00:00+01 |
13997 | 36 | 360 | 83 | 360 | 2022-02-22 04:00:00+01 |
13997 | 0 | 360 | 2 | 360 | 2022-02-22 05:00:00+01 |
13997 | 1 | 360 | 15 | 360 | 2022-02-22 06:00:00+01 |
13997 | 11 | 360 | 159 | 360 | 2022-02-22 07:00:00+01 |
13997 | 21 | 360 | 409 | 360 | 2022-02-22 08:00:00+01 |
13997 | 25 | 360 | 1282 | 360 | 2022-02-22 09:00:00+01 |
13997 | 20 | 360 | 1201 | 360 | 2022-02-22 10:00:00+01 |
13997 | 30 | 360 | 1381 | 360 | 2022-02-22 11:00:00+01 |
13997 | 42 | 360 | 924 | 360 | 2022-02-22 12:00:00+01 |
14000 | 1 | 360 | 36 | 360 | 2022-02-22 00:00:00+01 |
14000 | 0 | 360 | 0 | 360 | 2022-02-22 01:00:00+01 |
14000 | 1 | 360 | 0 | 360 | 2022-02-22 02:00:00+01 |
14000 | 0 | 360 | 2 | 360 | 2022-02-22 03:00:00+01 |
14000 | 0 | 360 | 0 | 360 | 2022-02-22 04:00:00+01 |
14000 | 0 | 360 | 12 | 360 | 2022-02-22 05:00:00+01 |
14000 | 3 | 360 | 4 | 360 | 2022-02-22 06:00:00+01 |
14000 | 24 | 360 | 123 | 360 | 2022-02-22 07:00:00+01 |
14000 | 31 | 360 | 374 | 360 | 2022-02-22 08:00:00+01 |
14000 | 18 | 360 | 620 | 360 | 2022-02-22 09:00:00+01 |
14000 | 38 | 360 | 1616 | 360 | 2022-02-22 10:00:00+01 |
14000 | 36 | 360 | 1410 | 360 | 2022-02-22 11:00:00+01 |
14000 | 24 | 360 | 957 | 360 | 2022-02-22 12:00:00+01 |
我想获取最大流量的具体date_time值(这是根据字段计算的tftralacc、tfnscan、thtralacc 和 thnscan)对于每个cell_id.
我已经设法通过使用 Django 的 QuerySet 的 annotate()
和 group_by()
函数为每个 cell_id 获得最大值API:
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')
)
为每个 date_time 计算的 流量 如下所示:
我的代码成功了returns每个最大流量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 |
因为最大值只是获得 date_time 的手段,而不是目标。
注意:有一个问题描述了我的问题,但它的答案是指一个变通解决方案,这对我的问题是不可能的。
使用 models.Subquery
with models.OuterRef
加入 cell_id
字段。然后用queryset.annotate()
注解子查询max_traffic
。最后,使用 queryset.filter()
到 select 具有 traffic
等于 max_traffic
的行,并使用 .distinct()
删除重复行。
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) | Q(thnscan=0), then=0),
default=Round((F('tftralacc') * 1.0 / F('tfnscan')) +
(F('thtralacc') * 1.0 / F('thnscan')), 2),
output_field=models.FloatField()
)
)
counters_with_max_traffic = 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'),
).filter(cell_id=models.OuterRef("cell_id")).values("max_traffic")
result = counters_with_traffic.annotate(
max_traffic=models.Subquery(counters_with_max_traffic),
).filter(
traffic=models.F("max_traffic")
).values(
"cell_id", "max_traffic", "date_time"
).distinct("cell_id", "max_traffic")