Mam modelkę
class ItemPrice( models.Model ):
price = models.DecimalField ( max_digits = 8, decimal_places=2 )
....
Próbowałem tego obliczyć sumę price
w tym zestawie zapytań:
items = ItemPrice.objects.all().annotate(Sum('price'))
co jest nie tak w tym zapytaniu? czy jest inny sposób obliczenia sumy price
kolumny?
Wiem, że można to zrobić za pomocą pętli for na queryset, ale potrzebuję eleganckiego rozwiązania.
Dzięki!
Odpowiedzi:
Prawdopodobnie szukasz
aggregate
from django.db.models import Sum ItemPrice.objects.aggregate(Sum('price')) # returns {'price__sum': 1000} for example
źródło
{'price__sum':1000}
. Można uzyskać zmiennoprzecinkową / całkowitą zyourdict['price__sum']
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')}
źródło
key
być przechowywana sumavalue
.Użyj
.aggregate(Sum('column'))['column__sum']
mojego przykładu Reefer poniżejsum = Sale.objects.filter(type='Flour').aggregate(Sum('column'))['column__sum']
źródło
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
aggregate
zawsze 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.źródło
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 przedsum()
iteracją po niej.