问题描述
给定一个表格
Key | Value
----------------+-------------
A | 1
A | 2
B | 1
B | 2
C | 1
C | 2
如何使用 (keys,value)
生成所有 sql
的乘积?
这是所需的输出:
Group | Key | Value
---------+--------------+----
1 |A | 1
1 |B | 1
1 |C | 1
2 |A | 1
2 |B | 1
2 |C | 2
3 |A | 1
3 |B | 2
3 |C | 1
4 |A | 1
4 |B | 2
4 |C | 2
5 |A | 2
5 |B | 2
5 |C | 2
6 |A | 2
6 |B | 1
6 |C | 2
7 |A | 2
7 |B | 2
7 |C | 1
8 |A | 2
8 |B | 1
8 |C | 1
为了说明目的,我可以在 Python
中使用:
In [1]: from itertools import product
In [2]: list(product([('A',1),('A',2)],[('B',('B',[('C',('C',2)]))
Out[2]:
[(('A',1)),(('A',2)),2),2))]
在我的实际应用中,(key,value)
对的数量不是提前固定的。
解决方法
您可以使用递归 CTE 来实现这一点——但将值放入单个列中会更简单:
with recursive kv as (
select key,value,dense_rank() over (order by key) as seqnum
from t
),cte(kv,seqnum) as (
select array[row(key,value)] as kv,1 as seqnum
from kv
where seqnum = 1
union all
select kv || row(kv.key,kv.value),kv.seqnum
from cte join
kv
on kv.seqnum = kv + 1
)
select cte.*,row_number() over (order by seqnum)
from cte;
如果您愿意,您可以取消嵌套数组以获取单独的行。
不幸的是,我手头没有 Presto/Trino 来检查语法。
,没有直接的方法来完成您的要求,但这是一种可能的方法:
WITH t(key,value) AS (
VALUES
('A',1),('A',2),('B',('C',2)
),grouped AS (
SELECT
combinations(array_agg(ROW(key,value)),3) combinations,count(distinct key) key_count
FROM t
),combinations AS (
SELECT row_number() OVER () AS "group",combination
FROM grouped CROSS JOIN UNNEST(combinations) AS u(combination)
WHERE cardinality(array_distinct(transform(combination,e -> e[1]))) = key_count
),unnested AS (
SELECT "group",key,value
FROM combinations,UNNEST(combination) AS u(key,value)
ORDER BY "group","key"
)
SELECT * FROM unnested
=>
group | key | value
-------+-----+-------
1 | A | 1
1 | B | 1
1 | C | 1
2 | A | 1
2 | B | 2
2 | C | 1
3 | A | 2
3 | B | 1
3 | C | 1
4 | A | 2
4 | B | 2
4 | C | 1
5 | A | 1
5 | B | 1
5 | C | 2
6 | A | 1
6 | B | 2
6 | C | 2
7 | A | 2
7 | B | 1
7 | C | 2
8 | A | 2
8 | B | 2
8 | C | 2
(24 rows)
这是它的工作原理:
- 创建一个条目数组(即
ROW(key,value)
)并计算不同键的总数
- 使用
combinations
函数从该数组的元素生成所有可能的三向组合。这将产生一些“无效”组合:多次包含相同键的组合。 - 过滤生成的组合以排除不包含所有键的任何组合。使用
row_number
窗口函数为每个剩余的组合分配一个组 ID。 - 从组合数组中取消嵌套单个键/值对以生成您期望的输出。