我想从给定的数据集中获得所有可能的组合,但即使是空元素(即元素数量可变)
示例我们有数据和一个简单的查询来显示它们:
with t as ( select 1 as COL1, 2 as COL2, 3 as COL3 from dual )
select * from t;
或更佳的示例:(也许很容易解决)
select 1 as col from dual
union all
select 2 from dual
union all
select 3 from dual
是否可以创建显示以下结果的查询:
1 - -
1 2 -
1 2 3
1 3 -
1 3 2
2 - -
2 1 -
2 1 3
2 3 -
2 3 1
3 - -
3 1 -
3 1 2
3 2 -
3 2 1
答案 0 :(得分:1)
这里的一个困难是,您将输入分为三列,而希望将结果分为三列。除非您愿意使用动态SQL(这是一个单独的主题,这是一种高级技术,在大多数情况下也是一种不好的做法,并且实际上与组合语言的问题无关),否则您必须对数字进行硬编码(并且名称)中的列。
您可以按行而不是按列显示输入数据,并以
格式查询结果row_num col_num val
------- ------- ---
1 1 1
1 2 -
1 3 -
(这仅模仿您的第一个输出行)-与所有其他行类似-然后您不必对查询中的列数进行硬编码;然后,您可以轻松地修改下面的代码来解决这个更普遍的问题。
我在下面使用SYS_CONNECT_BY_PATH
,它限制了列数(以及输入中每列中值的长度);可以避免这种情况,但是用这种方式编写查询很有趣。
我假设您期望的输出中的破折号-
代表NULL
;如果您实际上想显示破折号,请在最后的NVL(..., -)
子句中使用SELECT
。
with
t (col1, col2, col3) as (
select 1 as col1, 2 as col2, 3 as col3 from dual
)
, prep (pth) as (
select sys_connect_by_path(val, '/') || '/'
from t
unpivot (val for col in (col1, col2, col3))
connect by nocycle prior col is not null
)
select to_number(substr(pth, instr(pth, '/', 1, 1) + 1,
instr(pth, '/', 1, 2) - instr(pth, '/', 1, 1) - 1)) col1,
to_number(substr(pth, instr(pth, '/', 1, 2) + 1,
instr(pth, '/', 1, 3) - instr(pth, '/', 1, 2) - 1)) col2,
to_number(substr(pth, instr(pth, '/', 1, 3) + 1,
instr(pth, '/', 1, 4) - instr(pth, '/', 1, 3) - 1)) col3
from prep
order by col1 nulls first, col2 nulls first, col3 nulls first
;
输出:
COL1 COL2 COL3
----- ----- -----
1
1 2
1 2 3
1 3
1 3 2
2
2 1
2 1 3
2 3
2 3 1
3
3 1
3 1 2
3 2
3 2 1