简体   繁体   English

从 Django 中的子查询聚合注释字段

[英]Aggregate annotated field from Subquery in Django

I'm trying to implement a subquery with Django ORM, but I can't find a working solution.我正在尝试使用 Django ORM 实现子查询,但我找不到有效的解决方案。 The SQL query that I would need to reverse-engineer is:我需要逆向工程的 SQL 查询是:

select t1.location, sum(t1.value_relative::numeric) as total
from (
    select
        administrative_division_id as "location",
        jsonb_array_elements("values"->'loss'->'values')->>'dim_value' as dim_value,
        jsonb_array_elements("values"->'loss'->'values')->>'value_relative' as value_relative
    from assessments_entrybaserisk
    where "values"->'scenario'->>'value' = 'Total'
) t1
where t1.dim_value::numeric = 2
group by t1.location

I tried to use Django Subquery like below:我尝试使用 Django 子查询,如下所示:

subq = EntryBaseRisk.objects \
    .filter(id=OuterRef('pk'), values__scenario__value='Total') \
    .annotate(
    _dim_value=Cast(
        KeyTextTransform('dim_value',
                         JsonbArrayElements(KeyTransform('values', KeyTransform('loss', 'values')))),
        IntegerField()),
    _value_relative=Cast(
        KeyTextTransform('value_relative',
                         JsonbArrayElements(KeyTransform('values', KeyTransform('loss', 'values')))),
        FloatField())) \
    .values('assessment', 'administrative_division', '_dim_value', '_value_relative')

data = EntryBaseRisk.objects \
    .annotate(
    dim_value=Subquery(subq.values('_dim_value'), output_field=IntegerField()),
    total_relative_value=Sum(Subquery(subq.values('_value_relative'),
                                      output_field=FloatField()))) \
    .filter(**filters) \
    .values('administrative_division', 'total_relative_value') \
    .order_by('administrative_division')

but I get an error ProgrammingError: more than one row returned by a subquery used as an expression .但我得到一个错误ProgrammingError: more than one row returned by a subquery used as an expression The problem is that SQL generated by Django is different from my SQL above, because it doesn't select from a select and it works only if the subquery is returning only one row. The problem is that SQL generated by Django is different from my SQL above, because it doesn't select from a select and it works only if the subquery is returning only one row. I can't perform the Sum aggregation in the subquery, because aggregate function calls cannot contain set-returning function calls.我无法在子查询中执行 Sum 聚合,因为聚合 function 调用不能包含集合返回 function 调用。 Is there another way to make Django generate an SQL as per my needs?还有另一种方法可以让 Django 根据我的需要生成 SQL 吗?

You can try something like this:你可以尝试这样的事情:

relative_subquery = subq.values('_value_relative').annotate(total=Sum("*")).values('total')
dim_subquery = subq.values('_dim_value')

data = EntryBaseRisk.objects.annotate(
    dim_value=Subquery(dim_subquery[:1], output_field=IntegerField()),
    total_relative_value=Subquery(relative_subquery, output_field=FloatField())) \
    .filter(**filters) \
    .values('administrative_division', 'total_relative_value') \
    .order_by('administrative_division')

Here I am summing the value _value_relative from the subq and using the first value of the _dim_value to be annotated with EntryBaseRisk queryset.在这里,我将_value_relative中的subq值求和,并使用 _dim_value 的第一个值用_dim_value EntryBaseRisk集进行注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM