简体   繁体   English

Django ORM:获取一个字段的最大值与对应的其他字段值

[英]Django ORM: Get maximum value of a field with corresponding other fields values

I have this Table ( Counters ):我有这张表(计数器):

cell_id cell_id tftralacc tftralac tfnscan扫描 thtralacc蒽醌 thnscan thnscan date_time约会时间
13997 13997 10 10 360 360 94 94 360 360 2022-02-22 00:00:00+01 2022-02-22 00:00:00+01
13997 13997 0 0 360 360 0 0 360 360 2022-02-22 01:00:00+01 2022-02-22 01:00:00+01
13997 13997 0 0 360 360 0 0 360 360 2022-02-22 02:00:00+01 2022-02-22 02:00:00+01
13997 13997 0 0 360 360 0 0 360 360 2022-02-22 03:00:00+01 2022-02-22 03:00:00+01
13997 13997 36 36 360 360 83 83 360 360 2022-02-22 04:00:00+01 2022-02-22 04:00:00+01
13997 13997 0 0 360 360 2 2个 360 360 2022-02-22 05:00:00+01 2022-02-22 05:00:00+01
13997 13997 1 1个 360 360 15 15 360 360 2022-02-22 06:00:00+01 2022-02-22 06:00:00+01
13997 13997 11 11 360 360 159 159 360 360 2022-02-22 07:00:00+01 2022-02-22 07:00:00+01
13997 13997 21 21 360 360 409 409 360 360 2022-02-22 08:00:00+01 2022-02-22 08:00:00+01
13997 13997 25 25 360 360 1282 1282 360 360 2022-02-22 09:00:00+01 2022-02-22 09:00:00+01
13997 13997 20 20 360 360 1201 1201 360 360 2022-02-22 10:00:00+01 2022-02-22 10:00:00+01
13997 13997 30 30 360 360 1381 1381 360 360 2022-02-22 11:00:00+01 2022-02-22 11:00:00+01
13997 13997 42 42 360 360 924 924 360 360 2022-02-22 12:00:00+01 2022-02-22 12:00:00+01
14000 14000 1 1个 360 360 36 36 360 360 2022-02-22 00:00:00+01 2022-02-22 00:00:00+01
14000 14000 0 0 360 360 0 0 360 360 2022-02-22 01:00:00+01 2022-02-22 01:00:00+01
14000 14000 1 1个 360 360 0 0 360 360 2022-02-22 02:00:00+01 2022-02-22 02:00:00+01
14000 14000 0 0 360 360 2 2个 360 360 2022-02-22 03:00:00+01 2022-02-22 03:00:00+01
14000 14000 0 0 360 360 0 0 360 360 2022-02-22 04:00:00+01 2022-02-22 04:00:00+01
14000 14000 0 0 360 360 12 12 360 360 2022-02-22 05:00:00+01 2022-02-22 05:00:00+01
14000 14000 3 3个 360 360 4 4个 360 360 2022-02-22 06:00:00+01 2022-02-22 06:00:00+01
14000 14000 24 24 360 360 123 123 360 360 2022-02-22 07:00:00+01 2022-02-22 07:00:00+01
14000 14000 31 31 360 360 374 374 360 360 2022-02-22 08:00:00+01 2022-02-22 08:00:00+01
14000 14000 18 18 360 360 620 620 360 360 2022-02-22 09:00:00+01 2022-02-22 09:00:00+01
14000 14000 38 38 360 360 1616 1616 360 360 2022-02-22 10:00:00+01 2022-02-22 10:00:00+01
14000 14000 36 36 360 360 1410 1410 360 360 2022-02-22 11:00:00+01 2022-02-22 11:00:00+01
14000 14000 24 24 360 360 957 957 360 360 2022-02-22 12:00:00+01 2022-02-22 12:00:00+01

I want to get the specific date_time value of the maximum traffic (which is calculated based on the the fields tftralacc , tfnscan , thtralacc and thnscan ) for every cell_id .我想获取每个cell_id的最大流量的特定date_time值(根据字段tftralacctfnscanthtralaccthnscan计算得出)。

I've managed to get this maximum value for every cell_id by using the annotate() and group_by() functions of the Django's QuerySet API:通过使用 Django 的 QuerySet API 的annotate()group_by()函数,我设法获得了每个cell_id的最大值:

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')
)

The calculated traffic for every date_time is demonstrated here:此处演示了每个date_time的计算流量 在此处输入图像描述

My code successfully returns the maximum traffic for every cell_id :我的代码成功返回了每个cell_id的最大流量:

cell_id cell_id max_traffic最大流量
13997 13997 3.92 3.92
14000 14000 4.59 4.59

But my goal is to get the Corresponding date_time value for every max value.但我的目标是为每个最大值获取相应的date_time值。 like this:像这样:

cell_id cell_id max_traffic最大流量 date_time约会时间
13997 13997 3.92 3.92 2022-02-22 11:00:00+01 2022-02-22 11:00:00+01
14000 14000 4.59 4.59 2022-02-22 10:00:00+01 2022-02-22 10:00:00+01

or或者

cell_id cell_id date_time约会时间
13997 13997 2022-02-22 11:00:00+01 2022-02-22 11:00:00+01
14000 14000 2022-02-22 10:00:00+01 2022-02-22 10:00:00+01

Because that max value is just a mean to get the date_time and not the goal.因为该最大值只是获得date_time而不是目标的手段。

Note: There is this question that describes my problem, but its answer refers to a work-around solution, which is not possible with my problem.注意:有这个问题描述了我的问题,但它的答案是指一个变通解决方案,这对我的问题来说是不可能的。 SO Question 所以问题

Use models.Subquery with models.OuterRef to join on cell_id field.使用models.Subquerymodels.OuterRef加入cell_id字段。 Then use queryset.annotate() to annotate the subquery with max_traffic .然后使用queryset.annotate()max_traffic注释子查询。 Finally, use queryset.filter() to select rows that have traffic equals to max_traffic and use .distinct() to remove duplicate rows.最后,使用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")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM