1

我有一个包含多个列的 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

1 回答 1

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子句中作为此 Oracle 错误的解决方法。

于 2013-09-26T17:31:56.523 回答