Как использовать функцию PostgreSQL ArrayAgg для сгруппированного по запросу набора в Django ORM?

Для простоты у меня есть четыре таблицы (A, B, Category и Relation), таблица Relation хранит интенсивность A в B, а Category хранит тип B.

A <--- Relation ---> B ---> Category

Я пытаюсь исключить объединения в своем запросе, чтобы сократить время вычислений, используя PostgreSQL ArrayAgg и функцию индексации базы данных, основанную на этой сути. (Поскольку существует 18000 отношений, 4000 B и 1500 категорий, мои расчеты каждого отчета занимают почти два часа), и я получаю ошибку: psycopg2.ProgrammingError: агрегатные функции не разрешены в GROUP BY LINE 1: ... U0."id", U2."B" С U0."id" = ЛЮБОЙ ((ARRAY_AGG(...

Я использовал решение Брэда Мартсбергера для моего предыдущего вопроса, чтобы вычислить сумму интенсивности каждого А, произошедшего в В, сгруппированных по категориям В, Минимум и максимум рассчитанных сумм интенсивности в каждой категории В и частоту появления каждого А в каждой категории В и появление самого B в этой категории:

annotation0 = {
        'SumIntensity': Sum('ARelation__Intensity'),
        'A_Ids': ArrayAgg('id')
    } 
annotation1 = {
        'BOccurrence' : Count('id', distinct=True),
    }
sub_filter0 = Q(id__any=OuterRef('A_Ids'))
sub_filter1 = Q(Category_id=OuterRef('ARelation__B__Category_id'))
subquery0 = A.objects.filter(sub_filter0).values('id','ARelation__B__Category_id').annotate(**annotation0).order_by('-SumIntensity').values('SumIntensity')[:1]
subquery1 = A.objects.filter(sub_filter0).values('id','ARelation__B__Category_id').annotate(**annotation0).order_by('SumIntensity').values('SumIntensity')[:1]
subquery2 = B.objects.filter(sub_filter1).values('Category_id').annotate(**annotation1).values('BOccurrence')[:1]
result = A.objects.values(
        'id','id','ARelation__B__Category_id'
    ).annotate(
        **annotation0
    )
result = result.annotate(MaxAIntensity=Subquery(subquery0))
result = result.annotate(MinAIntensity=Subquery(subquery1))
result = result.annotate(BOccurrence=Subquery(subquery2))
result = result.annotate(
        AOccurrence=Count('id', distinct=False)
)

Как я могу решить проблему?

Есть ли другие эффективные альтернативы этому?

0 ответов

Другие вопросы по тегам