Django:计算来自同一模型的行上的字段之间的差异

Django:计算来自同一模型的行上的字段之间的差异,django,django-queryset,django-2.0,Django,Django Queryset,Django 2.0,我有一个模型,表示从运动项目开始跑步的持续时间: 类时间模型。模型: 参赛者 bib=models.ForeignKeyBib,on_delete=models.CASCADE 时间点。在0公里、5公里和终点都可能是一个 计时点=models.ForeignKeyTimingPoint,在_delete=models.CASCADE上 从开始到结束的持续时间 时间=models.FloatField 我想计算每个bib的两个计时点之间的持续时间。结果应该是一个查询集,每个bib对应一行。我认为,

我有一个模型,表示从运动项目开始跑步的持续时间:

类时间模型。模型: 参赛者 bib=models.ForeignKeyBib,on_delete=models.CASCADE 时间点。在0公里、5公里和终点都可能是一个 计时点=models.ForeignKeyTimingPoint,在_delete=models.CASCADE上 从开始到结束的持续时间 时间=models.FloatField 我想计算每个bib的两个计时点之间的持续时间。结果应该是一个查询集,每个bib对应一行。我认为,如果数据获取和持续时间计算可以在一个数据库查询中完成,那么效率最高。这能做到吗?如何做到

为了明确目标,我现在是这样做的:异常处理已删除:

时间=[] 对于围嘴中的围嘴: from_time=time.objects.gettiming_point=from_point,bib=bib to_time=time.objects.gettiming_point=to_point,bib=bib times.append{'bib':bib'time':to_time.time-from_time.time,} 我希望避免多次访问数据库,我更希望结果可以是查询集,因为我希望能够执行诸如排序之类的其他操作。

在和更高版本中,我们可以使用.annotate。。使用像Min这样的聚合和筛选器=。。。对该聚合的条件,如:

from django.db.models import F, Min, Q

t2=Min('time__time', filter=Q(time__timing_point=to_point))
t1=Min('time__time', filter=Q(time__timing_point=from_point))

Bib.objects.annotate(dtime=t2-t1)
实际上,2和1分别是to_点和from_点的主键

如果同时对计时模型进行筛选,则可能会进一步提高查询效率:

from django.db.models import F, Min, Q

t2=Min('time__time', filter=Q(time__timing_point=to_point))
t1=Min('time__time', filter=Q(time__timing_point=from_point))

Bib.objects.filter(
    time__timing_point__in=[from_point, to_point]
).annotate(dtime=t2-t1)
这将导致一个如下所示的查询:

SELECT bib.*,
       (MIN(CASE WHEN time.timing_point_id = 2 THEN time.time ELSE NULL END) -
        MIN(CASE WHEN time.timing_point_id = 1 THEN time.time ELSE NULL END)) AS dtime
FROM bib
LEFT OUTER JOIN time ON bib.id = time.bib_id GROUP BY bib.id
SELECT bib.*,
       (MIN(CASE WHEN time.timing_point_id = 2 THEN time.time ELSE NULL END) -
        MIN(CASE WHEN time.timing_point_id = 2 THEN time.time ELSE NULL END)) AS dtime
FROM bib LEFT OUTER JOIN time ON bib.id = time.bib_id
WHERE time.timing_point_id IN (1, 2)
GROUP BY bib.id

你用的是什么Django版本?@WillemVanOnsem我用的是Django 2.2。我很快会尝试你建议的解决方案,但它看起来很有希望。非常感谢。现在这是一个可靠的答案。@WillemVanOnsem测试过,效果很好。非常感谢。