Сумма агрегированных значений в Django
Я пытаюсь выполнить следующий SQL-запрос в Django:
(Таблица содержит данные о покупках за каждый день для каждого места. Я хочу получить наибольшее количество покупок в каждом месте, затем сгруппировать их по штатам, чтобы увидеть, сколько максимально можно продать в каждом штате)
select state, type, sum(amount)
from (
select l.state, dd.type, max(amount) as amount
from daily_data dd
join locations l on l.id = dd.location_id
where dd.type in ('purchases', 'returns')
group by dd.location_id, dd.type
)
group by state, type
Где я получаю вот это:
NY,purchases,80
NY, returns,6
Maine,purchases,125
Maine, returns,12
Но я застрял на том, как добиться этого в django.
Я попробовал следующее:
daily_data.objects.filter(type__in=['purchases', 'returns']
).values('location', 'type'
).annotate(total=Max('amount')
).values('location__state','type'
).annotate(sum=Sum('total'))
Но я получаю ошибку django.core.exceptions.FieldError: Cannot compute Sum('total'): 'total' is an aggregate
Я даже пробовал использовать подзапрос, но он генерирует плохой sql-запрос, в результате чего запрос выполняется бесконечно долго.
subquery = daily_data.objects.filter(
location=OuterRef('location'),
type=OuterRef('type')
).values('location', 'type').annotate(
max_amount=Max('amount')
).values('max_amount')
annotated_data = daily_data.objects.filter(
type__in=['purchases', 'returns']
).annotate(
max_amount=Subquery(subquery)
).values(
'location__state', 'type'
).annotate(
total_max_amount=Sum('max_amount')
).order_by('location__state', 'type')
Это генерирует:
SELECT "state", "type", SUM((
SELECT MAX(U0."amount") AS "total" FROM "daily_data" U0
INNER JOIN "locations" U1 ON (U0."location_id" = U1."id")
WHERE (U1."state" = ("state") AND U2."type" = "type") GROUP BY U0."location_id", U2."type")) AS "total"
FROM "daily_data"
INNER JOIN "locations" ON ("location_id" = "locations"."id") WHERE where "type" in ('purchases', 'returns')
GROUP BY "state", "type"
что избыточно и дорого... И я не успел увидеть результат, так как он загружается вечно...
Привет, я не эксперт в django orm, но для меня, когда программное создание запроса становится сложным при использовании django или spring (java framework), я часто просто предпочитаю писать sql напрямую, и django предоставляет вам такую возможность
где вы можете просто
result=daily_data.objects.raw(
"""
select state, type, sum(amount)
from (
select l.state, dd.type, max(amount) as amount
from daily_data dd
join locations l on l.id = dd.location_id
where dd.type in ('purchases', 'returns')
group by dd.location_id, dd.type
)
group by state, type
"""
)
for value in result.iterator():
print(value)
и использовать итератор для просмотра значений, хотя это всего лишь предложение, надеюсь, оно поможет :)
примечание: пожалуйста, обязательно следуйте документации при использовании метода raw для предотвращения sql-инъекций.