Как суммировать с условием в кверисете Django
Я пытаюсь суммировать запрос Django с условием. Предположим, у меня есть некоторые данные следующего вида:
| Name | Type |
---------------
| a | x |
| b | z |
| c | x |
| d | x |
| e | y |
| f | x |
| g | x |
| h | y |
| i | x |
| j | x |
| k | x |
| l | x |
Эти типы являются строковыми и имеют значения, например x = 1, y = 25, z = -3
Как суммировать все значения без цикла? В настоящее время используется цикл.
data = A.objects.all()
sum = 0
mapp = {'x': 1, 'y': 25, 'z': -3}
for datum in list(data):
sum = sum + mapp[datum.type]
print(sum)
Вы можете сократить это следующим образом:
sum(mapp.get(o['Type'],0) for o in data)
или проще, если вы доверяете данным, что они имеют все допустимые типы:
sum(mapp[o['Type']] for o in data)
(Не доверяйте данным)
Если отображение x = 1, y = 25
и т.д... происходит из другой таблицы, вы можете использовать некоторые SQL вуду, чтобы позволить базе данных обрабатывать суммирование за вас. В противном случае вам придется (тем или иным способом) перебирать все результаты и суммировать их.
Теоретически можно также просто подсчитать количество x
, y
и z
в таблице и получить sum = x*count_of_x + y*count_of_y + z*count_of_z
, исходя из того, как структурирован пример.
Для выполнения вычисления внутри базы данных используйте Queryset.aggregate()
с агрегатным выражением, которое использует Case
/When
:
from django.db.models import Sum, Case, When
A.objects.all().aggregate(
amount=Sum(Case(
When(type="x", then=1),
When(type="y", then=25),
When(type="z", then=-3),
default=0,
output_field=FloatField()
))
)