SQL - 分区的笛卡尔积

SQL - cartesian product of PARTITIONs

有一个非常复杂的查询,我一个人无法解决。在查询的table中有5列:PK_ID,它是值的唯一标识符,ID,它连接一组聚合值,count,其中表示应该聚合多少个值组(如果没有足够的值,则应从查询结果中省略具有 ID 的组), num 表示聚合的数量组内的值,以及要聚合的 value

(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 似乎只有在 JOINed tables 是预先知道的,但是有 count 并发症。 count 本身可能(我的意思是它不会,但它可以)范围从 2infinity

我想过用 WINDOW 函数、PARTITION BYIDnum 来处理它,但之后我就卡住了,因为那里似乎没有办法得到这些分区的笛卡尔积。

我应该收工并寻找另一种方法来处理数据,还是有办法编写这样的查询?

这看起来像是一个图遍历问题 - 需要递归查询。

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 开始并遵循所有可能的路径。外部查询仅在路径末尾进行过滤。

Demo on 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}