【问题标题】:Django Select Query Time DiffDjango选择查询时间差异
【发布时间】: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


    【解决方案1】:

    这可以完全通过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()))
    

    【讨论】:

    • 从 Django 1.10 开始,这应该是实现 OP 要求的首选方式。或者,您可以跳过ExpressionWrapper,直接使用Timer.objects.annotate(duration=F('end_time') - F('start_time'))。在这种情况下,duration 将包含 end_timestart_time 之间的差异(以微秒为单位)。
    • 除非您有时区信息,如果没有ExpressionWrapperDurationField,这将无法工作
    【解决方案2】:

    QuerySet.extra() 将允许您为列指定任意表达式。请注意,结果将取决于 DB。

    【讨论】:

    • 自从提出这个问题后,我已经改变了我的表设计,而且我还是使用了原始 SQL;尽管如此,我觉得这正是我在 django 文档中寻找但找不到的信息的瑰宝!谢谢!
    【解决方案3】:

    在我看来,最简单的方法是添加带有差异的第三列,并在每次像这样修改对象时更新它:

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

    【讨论】:

    • 这对我来说似乎是糟糕的桌子设计。为什么要在我的表中添加一个包含冗余数据的列?从数据建模的角度来看,保存冗余数据不仅愚蠢,而且这种解决方案还降低了我的应用程序的可扩展性。
    • 我必须同意建模的观点,这是一种反规范化(一个根本没有隐藏的事实)。但从可扩展性的角度来看,我认为你错了。每当您使用该差异进行查询时,它们会更快,这就是可伸缩性的全部意义所在。
    • 你是对的,查询确实会更快。当我将数据存储到表中时,只会增加额外的开销,但单个记录插入开销显然比处理整个表内容的开销更“有害”。用户在创建数据时甚至不会注意到延迟。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2018-11-07
      • 2010-11-12
      • 2019-05-17
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多