0

我正在尝试使用 Django ORM 实现子查询,但找不到有效的解决方案。我需要逆向工程的 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

我尝试使用 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')

但我得到一个错误ProgrammingError: more than one row returned by a subquery used as an expression。问题是 Django 生成的 SQL 与我上面的 SQL 不同,因为它不会从选择中进行选择,并且仅在子查询仅返回一行时才有效。我无法在子查询中执行 Sum 聚合,因为聚合函数调用不能包含集合返回函数调用。有没有另一种方法可以让 Django 根据我的需要生成 SQL?

4

1 回答 1

0

你可以尝试这样的事情:

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')

在这里,我对_value_relative来自的值求和,并使用要用查询集注释subq的第一个值。_dim_valueEntryBaseRisk

于 2020-08-06T08:38:50.203 回答