我正在尝试在 Django 中实现以下 SQL 查询:
(该表包含每个地点每天的购买量。我想获得每个地点的最大数量,然后按州对它们进行分组,看看每个州最多可以出售多少)
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 框架)以编程方式创建查询变得复杂时,我通常更喜欢直接编写我的 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注入。