有一个非常复杂的查询,我无法独自思考。在查询的表中有5列:PK_ID
,它是值的唯一标识符,ID
,它连接一个组中的聚合值,count
,它说应该聚合多少个值组(如果没有足够的值组,则应该从查询结果中删除具有这样的ID
的组(,num
,它说组内聚合值的数量,以及待聚合的CCD_ 6。
(Table T1)
PK_ID | ID | num | count | value
------+-------+-------+--------+--------
1 | 1 | 1 | 3 | A
------+-------+-------+--------+--------
2 | 1 | 2 | 3 | B
------+-------+-------+--------+--------
3 | 1 | 3 | 3 | C
------+-------+-------+--------+--------
4 | 1 | 1 | 3 | D
------+-------+-------+--------+--------
5 | 1 | 3 | 3 | E
------+-------+-------+--------+--------
6 | 1 | 2 | 3 | F
------+-------+-------+--------+--------
7 | 1 | 3 | 3 | G
------+-------+-------+--------+--------
8 | 2 | 1 | 2 | H
------+-------+-------+--------+--------
9 | 2 | 2 | 2 | I
------+-------+-------+--------+--------
10 | 2 | 1 | 2 | J
------+-------+-------+--------+--------
11 | 3 | 1 | 5 | X
这种查询的结果是:
PK_ID | T1_ID | cross_aggr | T1_PK_IDs
------+-------+------------+-----------
1 | 1 | {A, B, C} | {1, 2, 3}
------+-------+------------+-----------
2 | 1 | {A, B, E} | {1, 2, 5}
------+-------+------------+-----------
3 | 1 | {A, B, G} | {1, 2, 7}
------+-------+------------+-----------
4 | 1 | {A, F, C} | {1, 6, 3}
------+-------+------------+-----------
5 | 1 | {A, F, E} | {1, 6, 5}
------+-------+------------+-----------
6 | 1 | {A, F, G} | {1, 6, 7}
------+-------+------------+-----------
7 | 1 | {D, B, C} | {4, 2, 3}
------+-------+------------+-----------
8 | 1 | {D, B, E} | {4, 2, 5}
------+-------+------------+-----------
9 | 1 | {D, B, G} | {4, 2, 7}
------+-------+------------+-----------
10 | 1 | {D, F, C} | {4, 6, 3}
------+-------+------------+-----------
11 | 1 | {D, F, E} | {4, 6, 5}
------+-------+------------+-----------
12 | 1 | {D, F, G} | {4, 6, 7}
------+-------+------------+-----------
13 | 2 | {H, I} | {8, 9}
------+-------+------------+-----------
14 | 2 | {J, I} | {10, 9}
因此,它返回了每个组内value
的每一个可能组合,由ID
定义,并由count
描述,这些值按每个单独的num
的顺序进行聚合。
看起来我必须使用CROSS JOIN
(以与线性代数中的笛卡尔乘积相同的方式(,但CROSS JOIN
似乎只有在事先知道JOIN
ed表的数量的情况下才能工作,但存在count
的复杂性。count
本身可能(我的意思是它没有,但它可能(在2
到infinity
的范围内。
我曾想过用WINDOW
函数、PARTITION BY
、ID
和num
来处理它,但在那之后我就陷入了困境,因为似乎没有办法得到这些分区的笛卡尔乘积。
我应该到此为止,找到另一种方法来处理数据,还是有一种方法可以组成这样的查询?
这读起来像是一个图遍历问题,需要递归查询。
with recursive cte as (
select id, num, cnt, 1 as lvl,
array[value::text] as arr_values,
array[pk_id::int] as arr_pk_id
from mytable where num = 1
union all
select c.id, t.num, c.cnt, c.lvl + 1,
c.arr_values || t.value::text,
c.arr_pk_id || t.pk_id
from cte c
inner join mytable t
on t.id = c.id
and t.num = c.num + 1
and t.num <= c.cnt
)
select id, arr_values, arr_pk_id
from cte
where array_length(arr_pk_id, 1) = cnt
order by arr_pk_id
对于每个id
,递归查询在num
1
处开始,并遵循所有可能的路径。外部查询只过滤路径的末尾。
DB Fiddle上的演示:
id|arr_values|arr_pk_id-:|:--------|:--------1|{A,B,C}|{1,2,3}1|{A,B,E}|{1,2,5}1|{A,B,G}|{1,2,7}1|{A,F,C}|{1,6,3}1|{A,F,E}|{1,6,5}1|{A,F,G}|{1,6,7}1|{D,B,C}|{4,2,3}1|{D,B,E}|{4,2,5}1|{D,B,G}|{4,2,7}1|{D,F,C}|{4,6,3}1|{D,F,E}|{4,6,5}1|{D,F,G}|{4,6,7}2|{H,I}|{8,9}2|{J,I}|{10,9}