Django ORM 中的自定义 TruncFunc
Custom TruncFunc in Django ORM
我有一个具有以下结构的 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 天间隔的聚合值和该间隔第二天的索引的查询集?
我想这在数据库级别是不可能的(并且 Trunc 是数据库级别的函数),因为 Postgres and Oracle.
只支持月、日、周等。
所以我建议使用 TruncDay
,然后添加 python 代码以按 3 天对它们进行分组。
下面的应该可以工作,虽然它有点难看。
如果您得到每一行的日期和最小日期之间的天数差异,您可以利用此差异的 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')
)
我有一个具有以下结构的 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 天间隔的聚合值和该间隔第二天的索引的查询集?
我想这在数据库级别是不可能的(并且 Trunc 是数据库级别的函数),因为 Postgres and Oracle.
只支持月、日、周等。所以我建议使用 TruncDay
,然后添加 python 代码以按 3 天对它们进行分组。
下面的应该可以工作,虽然它有点难看。
如果您得到每一行的日期和最小日期之间的天数差异,您可以利用此差异的 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')
)