我有一个带有多个列的Oracle表,其中一些填充了变量,有大量可能的变量,下面的示例并非详尽无遗。
ID Col1 Col2 Col3
--------------------
1 A B
2 B A D
3 B C
4 C B
5 B B
6 E D
7 B A C
我需要创建一个解析每行中变量的查询:
ID Col1 Col2 Col3
--------------------
1 A B
2 A B D
3 B C
4 B C
5 B B
6 D E
7 A B C
我正在寻找一个优雅的解决方案,因为现实世界的问题有20列,最多40个不同的变量(每个长度最多4个字符)和数百万条记录。
答案 0 :(得分:1)
以下是Oracle 10g
及更高版本的变体。因为原始数据集中存在大量行,所以我将尽量避免涉及在完整结果集顶部进行分组和分析功能的解决方案。
此示例的基表:
create table tab1 (
ID number,
col1 varchar2(4),
col2 varchar2(4),
col3 varchar2(4),
col4 varchar2(4)
)
首先,将每个ID
的所有列收集到已排序的集合中:
select
tab1.ID,
cast( multiset(
select
decode(level,
1, tab1.col1,
2, tab1.col2,
3, tab1.col3,
4, tab1.col4,
null
)
from dual
connect by level <= 4
order by
decode(level,
1, tab1.col1,
2, tab1.col2,
3, tab1.col3,
4, tab1.col4,
null
)
nulls last
) as sys.ODCIVarchar2List) sorted_values
from tab1;
拥有这样的数据集,可以在保持指定顺序的同时将值解码回列:
select
ID,
(
select column_value
from table(data_list.sorted_values)
where rownum = 1
) as col1,
(
select max(decode(rownum, 2, column_value, null))
from table(data_list.sorted_values)
) as col2,
(
select max(decode(rownum, 3, column_value, null))
from table(data_list.sorted_values)
) as col3,
(
select max(decode(rownum, 4, column_value, null))
from table(data_list.sorted_values)
) as col4
from (
select
rownum, -- this needed as workaround for Oracle bug
tab1.ID,
cast( multiset(
select
decode(level,
1, tab1.col1,
2, tab1.col2,
3, tab1.col3,
4, tab1.col4,
null
)
from dual
connect by level <= 4
order by
decode(level,
1, tab1.col1,
2, tab1.col2,
3, tab1.col3,
4, tab1.col4,
null
)
nulls last
) as sys.ODCIVarchar2List) sorted_values
from tab1
)
data_list
<强> SQLFiddle test 强>
请注意,内部rownum
子句中必须select
作为this Oracle error的解决方法。