【问题标题】:Annotate a queryset with the average date difference? (django)用平均日期差异注释查询集? (django)
【发布时间】:2011-03-09 01:10:54
【问题描述】:

我到处寻找答案,但找不到任何东西。也许这只是一个愚蠢的问题或一个非常棘手的问题。这里是:

假设我的模型是这样的(伪 django 代码):

Event
  type = ForeignKey(EventType)
  name = CharField
  date_start = DateField
  date_end = DateField

EventType
  name = CharField

我想知道的是每种事件类型的平均持续时间。我现在要做的是计算每次创建新事件时的平均持续时间(保存方法)并将其存储在 EventType 的 average_duration 列中。这种方法的问题是我无法回答诸如“X 类型事件的平均持续时间是多少,Y 年”之类的问题。因此,与其添加更多列来回答此类问题,我更愿意“实时”完成。

这可以通过注释查询集来完成吗?首先,我必须获取每种事件类型的日期差异,然后得出它们的平均值,然后用该平均值注释 Event 查询集。

【问题讨论】:

    标签: django date django-queryset annotate


    【解决方案1】:

    只是一个更新。在 Django >= 1.8 中可以这样做:

    from django.db.models import F, ExpressionWrapper, fields
    
    duration = ExpressionWrapper(F('date_end') - F('date_start'), output_field=fields.DurationField())
    
    events_with_duration = Event.objects.annotate(duration=duration)
    

    之后您可以运行以下查询:

    events_with_duration.filter(duration__gt=timedelta(days=10))
    

    【讨论】:

    • 不应该是date_end - date_start吗?
    • 在 Django 1.8 中测试,这在应用于聚合函数时似乎不起作用(例如 Event.objects.annotate(duration=duration).aggregrate(Avg('duration')) )跨度>
    • 相信你need gt 前的双下划线:duration__gt
    • @AliceHeaton 刚刚在 Django 1.10 中测试没有问题:Event.objects.annotate(duration=duration).aggregrate(Avg('duration')) 正确返回 {'duration__avg': datetime.timedelta(-1, 85408, 926663)}
    • 在 Django 2.1.10 中测试,没问题!对于视图,我使用 str(MODEL.duration),例如 'X days XX:XX:XX'
    【解决方案2】:

    您需要使用extra 方法创建一个查询集,以将日期差异添加到每一行

    然后使用aggregate 方法计算您刚刚添加的列的平均值:

    但请注意,此方法速度慢且无法扩展。将计算值存储在 event_type 上是您最好的选择。

    【讨论】:

      【解决方案3】:

      我认为您最好的选择是使用date_end - date_start 列创建一个 SQL 视图,在此视图上创建一个 django 模型,然后您将能够查询该视图并根据需要对其进行注释。我已经使用与您相似的模型完成了此操作,如果您需要,也许我可以为您提取一些有趣的代码。

      【讨论】:

      • 是的,如果您能提供一些代码示例,那就太好了,谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 2015-09-09
      • 1970-01-01
      • 2018-09-15
      • 2020-10-05
      • 2019-10-12
      相关资源
      最近更新 更多