Tengo un modelo de Django con la siguiente estructura:
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) Me gustaría tener una Avg de agregado promedio en objetos cada 3 días.
por ejemplo, escribo un conjunto de consultas que hace esta agregación para cada día o con algo como la función TruncDay .
queryset = BBPerformance.objects.annotate(day=TruncDay('created_at')).values('day').annotate(marketcap_avg=Avg('marketcap_change'),bb_avg=Avg('bb_change')¿Cómo puedo tener un conjunto de consultas del valor agregado con un intervalo de 3 días y el índice del segundo día de ese intervalo?
Supongo que es imposible en el nivel de base de datos (y Trunc es la función de nivel de base de datos) ya que solo se admiten meses, días, semanas, etc. en Postgres y Oracle .
Entonces, lo que sugeriría es usar TruncDay y luego agregar el código python para agruparlos por 3 días.
Lo siguiente debería funcionar, aunque es un poco feo.
Si obtiene la diferencia en días entre la fecha de cada fila y la fecha mínima, puede tomar el Mod de esta diferencia para calcular cuántos días necesita cambiar para obtener la fecha "media". Esta fecha intermedia se puede agrupar usando una consulta de valores
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') )