【问题标题】:Custom TruncFunc in Django ORMDjango ORM 中的自定义 TruncFunc
【发布时间】:2022-01-24 11:49:25
【问题描述】:

我有一个具有以下结构的 Django 模型:

class BBPerformance(models.Model):
    marketcap_change = models.FloatField(verbose_name="marketcap change", null=True, blank=True)
    bb_change = models.FloatField(verbose_name="bestbuy change", null=True, blank=True)
    created_at = models.DateTimeField(verbose_name="created at", auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name="updated at", auto_now=True)

我希望每 3 天对对象进行一次 Avg 聚合函数。
例如,我编写了一个查询集,它每天或使用类似 TruncDay 的函数进行聚合。

queryset = BBPerformance.objects.annotate(day=TruncDay('created_at')).values('day').annotate(marketcap_avg=Avg('marketcap_change'),bb_avg=Avg('bb_change')

我怎样才能有一个以 3 天为间隔的聚合值的查询集和该间隔第二天的索引?

【问题讨论】:

  • 你使用什么数据库?
  • 我在我的项目中使用 Postgres。

标签: python django postgresql django-orm


【解决方案1】:

我想这在 DB 级别是不可能的(而 Trunc 是 DB 级别的函数),因为 PostgresOracle 仅支持月、周等。

所以我建议使用TruncDay,然后添加 python 代码将它们按 3 天分组。

【讨论】:

    【解决方案2】:

    以下应该可以工作,虽然它有点难看。

    如果您得到每行日期和最小日期之间的天数差异,您可以使用此差异的Mod 来计算您需要转换多少天才能获得“中间”日期。然后可以使用值查询对这个中间日期进行分组

    import datetime
    from django.db.models import F, IntegerField, Avg, Min, DurationField, DateField
    from django.db.models.functions import Cast, Mod, Extract
    
    BBPerformance.objects.order_by(
        'created_at'
    ).annotate(
        diff=F('created_at__date') - BBPerformance.objects.aggregate(min=Min('created_at__date'))['min']
    ).annotate(
        diff_days=Cast(Extract('diff', 'days'), output_field=IntegerField())
    ).annotate(
        to_shift=Mod('diff_days', 3) - 1
    ).annotate(
        grouped_date=Cast(F('created_at__date') - Cast(F('to_shift') * datetime.timedelta(days=1), output_field=DurationField()), output_field=DateField())
    ).order_by(
        'grouped_date'
    ).values(
        'grouped_date'
    ).annotate(
        marketcap_avg=Avg('marketcap_change'),
        bb_avg=Avg('bb_change')
    )
    

    【讨论】:

      猜你喜欢
      • 2020-01-09
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 2012-09-23
      • 2011-06-18
      相关资源
      最近更新 更多