tengo un modelo:
class MyModel(models.Model): store_id = models.TextField() day_dt = models.DateField() param1 = models.IntegerField() param2 = models.IntegerField()Ejemplo de algunos datos:
store_id | day_dt | param1 | param2 ---------------------------------------- STORE1 | 2021-09-30 | 10 | 30 STORE2 | 2021-09-31 | 20 | 40 .... STORE1 | 2021-10-01 | 4 | 5 STORE1 | 2021-10-02 | 6 | 10 STORE1 | 2021-10-03 | 2 | 5 STORE2 | 2021-10-02 | 3 | 7 STORE2 | 2021-10-03 | 1 | 19 .... Necesito dividir los datos en grupos por store_id e intervalo ( day_dt debe estar entre 2021-10-01 y 2021-10-04 ):
STORE1 | 2021-10-01 STORE1 | 2021-10-02 STORE1 | 2021-10-03y
STORE2 | 2021-10-02 STORE2 | 2021-10-03y luego aplicar a cada uno (de dos) la agregación de grupos: Avg('param1') y Avg('param2').
El resultado esperado para el ejemplo de datos:
store_id | param1_avg | param2_avg ---------------------------------- STORE1 | 6 | 10 STORE2 | 2 | 13¿Cómo podría hacer esta agregación con ORM?
Puedes implementar esto con:
from django.db.models import Avg MyModel.objects .filter( date_dt__range=('2021-10-01', '2021-10-04') ).values( 'store_id' ).annotate( param1_avg=Avg('param1'), param2_avg=Avg('param2') ).order_by( 'store_id' ) Esto devolverá un QuerySet de diccionarios que se verá así:
<QuerySet [ {'store_id': 'STORE1', param1_avg: 6, param2_avg: 10}, {'store_id': 'STORE2', param1_avg: 2, param2_avg: 13} ]> las tiendas que no tienen registros de MyModel para el intervalo de fechas dado no tendrán un objeto de diccionario en el conjunto de consultas resultante.
Puede utilizar esta solución que es la forma más sencilla.
Pero la solución de Django es usar Expression y escribir sus propias Query Expressions . En esta solución, crea una expresión como Hours y la usa en la función de annotate como: .annotate(Hours("day_dt")) . Debe anular la función as_sql para escribir su método SQL personalizado o anular las funciones as_sqlite y as_postgresql para diferentes DBMS de soporte.