Django: вычислить сумму значений столбца с помощью запроса

92

У меня есть модель

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

Я пробовал это, чтобы вычислить сумму priceв этом наборе запросов:

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

что не так в этом запросе? или есть ли другой способ вычислить сумму priceстолбца?

Я знаю, что это можно сделать, используя цикл for в наборе запросов, но мне нужно элегантное решение.

Благодарность!

Ахсан
источник
Отвечает ли это на ваш вопрос? Django SUM Query?
Flimm,

Ответы:

196

Вы, наверное, ищете aggregate

from django.db.models import Sum

ItemPrice.objects.aggregate(Sum('price'))
# returns {'price__sum': 1000} for example
Мэтт
источник
1
Как я могу получить общее количество, цена которого = 5000?
Анудж Шарма
6
Помните, что возвращает словарь не с плавающей точкой или целым числом, например {'price__sum':1000}. Можно получить числа с плавающей точкой или целое число с помощьюyourdict['price__sum']
Джош
35

Аннотации добавляет поле к результатам:

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

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

Агрегат возвращает запрос с запрошенным результатом:

>> Order.objects.aggregate(total_price=Sum('price'))
{'total_price': Decimal('1260.00')}
Иброхим Ерматов
источник
Я признателен за то, что вы показали, как указать, в котором keyследует хранить сумму value.
MikeyE
32

Используйте .aggregate(Sum('column'))['column__sum']мой пример ниже

sum = Sale.objects.filter(type='Flour').aggregate(Sum('column'))['column__sum']
угали мягкий
источник
5

Используя профилировщик cProfile , я обнаружил, что в моей среде разработки более эффективно (быстрее) суммировать значения списка, чем агрегировать с использованием Sum(). например:

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.

Я тестировал это в разных контекстах, и мне кажется, что использование aggregateвсегда занимает больше времени для получения того же результата. Хотя я подозреваю, что использование его вместо суммирования списка может иметь преимущества с точки зрения памяти.

Дядя Саам
источник
1
В качестве альтернативы, используйте выражение генератора вместо списка: sum_a = sum(item.column for item in queryset). Единственное отличие - удаленные []s. Это экономит место в памяти для вычисления всего списка перед его sum()итерацией.
Code-Apprentice