Oracle:这种方式转换数据的方法是什么?

时间:2011-04-28 12:35:52

标签: sql oracle plsql

有没有办法用SQL查询将第一个表映射到第二个表,或者如果太复杂,是否有PL / SQL块?

原始

--------------------------------------
|  col1   | col2   | col3   | col4   |
--------------------------------------
|  key    | case 1 | case 2 | case 3 |
|  value1 | v1c1   | v1c2   | v1c3   |
|  value2 | v2c1   | v2c2   | v2c3   |
--------------------------------------

目标

-----------------------------
| key     | case   | result |
-----------------------------
| value1  | case 1 | v1c1   |
| value1  | case 2 | v1c2   |
| value1  | case 3 | v1c3   |
| value2  | case 1 | v2c1   |
| value2  | case 2 | v2c2   |
| value2  | case 3 | v2c3   |
-----------------------------

原始表可以具有可变数量的列,“key”是硬编码字符串,并且始终位于原始表的第1列中。没有其他行在第1列中具有“键”,因此该行是唯一的轴。

谢谢

4 个答案:

答案 0 :(得分:1)

  

原始表可以有一个变量   列数

真的?

直接的方法是选择和合并你想要的部分。

select col1 as key, 'case1' as case, col2 as result
from test
where col1 <> 'key'
union all
select col1 as key, 'case2' as case, col3 as result
from test
where col1 <> 'key'
union all
select col1 as key, 'case3' as case, col4 as result
from test
where col1 <> 'key'

直截了当,但不是动态的。

稍后。 。

根据您的评论。 。 。虽然我认为没必要。

select col1 as key, (select col2 from test where col1='key') as case, col2 as result
from test
where col1 <> 'key'
union all
select col1 as key, (select col3 from test where col1='key') as case, col3 as result
from test
where col1 <> 'key'
union all
select col1 as key, (select col4 from test where col1='key') as case, col4 as result
from test
where col1 <> 'key'

Oracle 11还支持UNPIVOT,我还没有使用过。

答案 1 :(得分:1)

我不知道哪些部分可以改变,但这应该是一个开始。如果列名称可以更改(键,案例1等),则必须使用另一个查询来获取正确的列名称。如果您有任何问题,请随时询问:

declare
    v_query VARCHAR2(5000);
    v_case VARCHAR2(255);
    v_colcount PLS_INTEGER;
begin
    -- Get number of columns
    select count(*)
    INTO v_colcount
    from user_tab_columns
    where table_name = 'T1';

    -- Build case statement to get correct value for result column
    v_case := 'case';

    for i in 1 .. v_colcount-1
    loop
        v_case := v_case||' when rn = '||to_char(i)||' then col'||to_char(i+1);
    end loop;

    v_case := v_case||' end result';

    -- Build final query
    v_query := 'select col1 key, ''case ''||rn case, '||v_case||'
        from t1
           cross join (
                select rownum rn
                from dual
                connect by level <= '||to_char(v_colcount-1)||'
            ) cj
        where col1 <> ''key''
        order by key, case';

     -- Display query (would probably be replaced with an insert using execute immediate)
    dbms_output.put_line(v_query);
end;

这会产生以下查询(假设您的原始表名为t1):

select col1 key, 'case '||rn case, case when rn = 1 then col2 when rn = 2 then col3 when rn = 3 then col4 end result
        from t1
           cross join (
                select rownum rn
                from dual
                connect by level <= 3
            ) cj
        where col1 <> 'key'
        order by key, case

答案 2 :(得分:1)

试试这个:

with data as
(select level l from dual connect by level <= 3)
  select col1,
  'case' || l as "case",
  decode(l,1,col2,2,col3,3,col4) as "values"
  from myTable, data
  order by 1,2;

干杯

答案 3 :(得分:1)

如果允许动态sql,则可以使用一个查询填写所有要求:

SELECT col1 as "key"
       ,extractvalue(dbms_xmlgen.getXMLType('select "' || tc.Column_Name ||
                                           '" as v from Original where col1 = ''key''')
                   ,'/ROWSET/ROW/V') "case"
       ,extractvalue(dbms_xmlgen.getXMLType('select "' || tc.Column_Name ||
                                           '" as v from Original where col1 = ''' ||
                                           replace(col1, '''', '''''') || '''')
                   ,'/ROWSET/ROW/V') "result"
FROM   Original
      ,(SELECT Column_Name
        FROM   All_Tab_Columns tc
        WHERE  tc.Owner = 'YOURSCHEMA'
        and    tc.Table_Name = 'ORIGINAL'
        and    Column_Name != 'COL1'
        ORDER  BY tc.COLUMN_ID) tc
WHERE  col1 != 'key'
ORDER  BY "key"
          ,"case"

根据要求提供更多详情:

  • dbms_xmlgen.getXMLType返回一个XmlType实例,该实例基本上是提供的查询字符串为XML的结果。 根节点的格式为ROWSET,每行的格式为ROW。每列也都是一个元素。 我正在创建的2个选择只返回一个值并使事情更容易,我给了他们一个列别名“V”,以便我知道从XML中选择哪个值。
  • extractValue是一个从XmlType返回XPath表达式结果的函数。 '/ ROWSET / ROW / V'从位于根节点ROWSET下的第一个ROW节点返回第一个V节点。
    &LT; ROWSET&GT;&LT; ROW&GT;&LT; V&GT;美国广播公司&LT; / V&GT;&LT; / ROW&GT;&LT; / ROWSET&GT;