4

为了简单起见,我有四个表(A、B、Category 和 Relation),Relation 表存储 B 中 A 的强度,Category 存储 B 的类型。

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

我正在尝试使用 PostgreSQL 的 ArrayAgg 和基于此gist的数据库的索引功能来消除查询中的连接以减少计算时间。(由于有 18000 个关系、4000 个 Bs 和 1500 个类别,我对每个报告的计算需要将近两个小时)并且我得到的错误是:psycopg2.ProgrammingError: aggregate functions are not allowed in GROUP BY LINE 1: ... U0 ."id", U2."B" HAVING U0."id" = ANY((ARRAY_AGG(...

我已使用Brad Martsberger 解决上一个问题的方法来计算按 B 的类别分组的 B 中发生的每个 A 强度的总和、B 的每个类别中计算的强度和的最小值和最大值以及每个 B 类别中每个 A 的发生率以及 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)
)

我该如何解决这个问题?

有没有其他有效的替代方案?

4

0 回答 0