Django: Oblicz sumę wartości kolumn za pomocą zapytania


92

Mam modelkę

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

Próbowałem tego obliczyć sumę pricew tym zestawie zapytań:

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

co jest nie tak w tym zapytaniu? czy jest inny sposób obliczenia sumy pricekolumny?

Wiem, że można to zrobić za pomocą pętli for na queryset, ale potrzebuję eleganckiego rozwiązania.

Dzięki!


Czy to odpowiada na twoje pytanie? Django SUM Query?
Flimm

Odpowiedzi:


196

Prawdopodobnie szukasz aggregate

from django.db.models import Sum

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

1
Jak mogę uzyskać całkowitą liczbę, której cena = 5000?
Anuj Sharma,

6
Pamiętaj zwraca słownik, a nie liczbę zmiennoprzecinkową / całkowitą, np {'price__sum':1000}. Można uzyskać zmiennoprzecinkową / całkowitą zyourdict['price__sum']
Josh

35

Adnotacja dodaje pole do wyników:

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

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

Aggregate zwraca dyktę z pytanym wynikiem:

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

Doceniam, że pokazałeś, jak określić, w którym ma keybyć przechowywana suma value.
MikeyE

32

Użyj .aggregate(Sum('column'))['column__sum']mojego przykładu Reefer poniżej

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

5

Używając profilera cProfile , stwierdzam, że w moim środowisku programistycznym wydajniejsze (szybsze) jest sumowanie wartości listy niż agregowanie przy użyciu Sum(). na przykład:

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.

Przetestowałem to w różnych kontekstach i wydaje się, że użycie aggregatezawsze trwa dłużej, aby uzyskać ten sam wynik. Chociaż podejrzewam, że pod względem pamięci może być korzyści, aby używać go zamiast sumowania listy.


1
Alternatywnie, użycie wyrażenia generatora zamiast listy: sum_a = sum(item.column for item in queryset). Jedyną różnicą jest usunięty []s. Oszczędza to miejsce w pamięci na obliczanie całej listy przed sum()iteracją po niej.
Code-Apprentice
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.