【发布时间】:2011-08-07 14:18:06
【问题描述】:
我正在尝试在 django 中查询一个数据库表,其中包括以下列:
id | start_time | end_time
我可以直接在查询中获取差异,而不是获取两者的单独值吗? 大意是这样的:
SELECT id, Diff(start_time, end_time) FROM myTable
【问题讨论】:
标签: django django-models django-queryset
我正在尝试在 django 中查询一个数据库表,其中包括以下列:
id | start_time | end_time
我可以直接在查询中获取差异,而不是获取两者的单独值吗? 大意是这样的:
SELECT id, Diff(start_time, end_time) FROM myTable
【问题讨论】:
标签: django django-models django-queryset
这可以完全通过Django 1.10 及以上的ORM 来完成。使用这样的模型:
class Timer(models.Model)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
您可以像这样使用持续时间注释对象:
from django.db.models import DurationField, ExpressionWrapper, F
Timer.objects.annotate(duration=ExpressionWrapper(F('end_time') - F('start_time'),
output_field=DurationField()))
【讨论】:
ExpressionWrapper,直接使用Timer.objects.annotate(duration=F('end_time') - F('start_time'))。在这种情况下,duration 将包含 end_time 和 start_time 之间的差异(以微秒为单位)。
ExpressionWrapper 和DurationField,这将无法工作
QuerySet.extra() 将允许您为列指定任意表达式。请注意,结果将取决于 DB。
【讨论】:
在我看来,最简单的方法是添加带有差异的第三列,并在每次像这样修改对象时更新它:
class Timer(models.Model)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
diff_time = models.DateTimeField()
def __init__(self, *args, **kwargs):
super(Timer, self).__init__(*args, **kwargs)
self.diff_time = self.end_time - self.start_time
def save(self, *args, **kwargs):
self.diff_time = self.end_time - self.start_time
super(Timer, self).save(*args, **kwargs)
我试图寻找一个带有注释的解决方案,但是在 mysql 和 postgres 中都不支持聚合函数。即使在哪里,似乎也可以很好地权衡一个额外的列,而不必计算每个查询的每一行的差异!
哦,你可以像这样检索你想要的:
Timer.objects.values('id', 'diff_time')
【讨论】:
从 Django 1.8 开始,extra is discouraged 支持 annotate+RawSQL。以下适用于 MySQL:
res = MyTable.objects.annotate(duration=RawSQL('datediff(endtime, starttime)', ()))
# examine the results
print res.values_list('duration', 'starttime', 'endtime')
【讨论】: