Django: calcula la suma de los valores de la columna a través de la consulta


92

Tengo un modelo

class ItemPrice( models.Model ):
     price = models.DecimalField ( max_digits = 8, decimal_places=2 )
     ....

Intenté esto para calcular la suma de priceen este conjunto de consultas:

items = ItemPrice.objects.all().annotate(Sum('price'))

¿Qué hay de malo en esta consulta? ¿O hay alguna otra forma de calcular la suma de la pricecolumna?

Sé que esto se puede hacer usando for loop en queryset pero necesito una solución elegante.

¡Gracias!


¿Responde esto a tu pregunta? ¿Consulta SUM de Django?
Flimm

Respuestas:


196

Probablemente estas buscando aggregate

from django.db.models import Sum

ItemPrice.objects.aggregate(Sum('price'))
# returns {'price__sum': 1000} for example

1
¿Cómo puedo obtener un recuento total cuyo precio = 5000?
Anuj Sharma

6
Recuerde que devuelve el diccionario, no flotante / entero, por ejemplo {'price__sum':1000}. Puede obtener flotante / entero conyourdict['price__sum']
Josh

35

Anotar agrega un campo a los resultados:

>> Order.objects.annotate(total_price=Sum('price'))
<QuerySet [<Order: L-555>, <Order: L-222>]>

>> orders.first().total_price
Decimal('340.00')

Agregado devuelve un dictado con el resultado solicitado:

>> Order.objects.aggregate(total_price=Sum('price'))
{'total_price': Decimal('1260.00')}

Le agradezco que me muestre cómo especificar el keypara almacenar la suma value.
MikeyE

32

Use .aggregate(Sum('column'))['column__sum']reefer mi ejemplo a continuación

sum = Sale.objects.filter(type='Flour').aggregate(Sum('column'))['column__sum']

5

Usando cProfile Profiler , encuentro que en mi entorno de desarrollo, es más eficiente (más rápido) sumar los valores de una lista que agregar usando Sum(). p.ej:

sum_a = sum([item.column for item in queryset]) # Definitely takes more memory.
sum_b = queryset.aggregate(Sum('column')).get('column__sum') # Takes about 20% more time.

Probé esto en diferentes contextos y parece que usarlo aggregatesiempre lleva más tiempo para producir el mismo resultado. Aunque sospecho que podría haber ventajas en cuanto a memoria para usarlo en lugar de sumar una lista.


1
También puede utilizar un generador de expresión en lugar de una lista: sum_a = sum(item.column for item in queryset). La única diferencia son los []s eliminados . Esto ahorra espacio en la memoria para calcular la lista completa antes de sum()iterar sobre ella.
Code-Apprentice
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.