在Oracle 11g中转置查询结果

时间:2014-12-02 10:35:42

标签: sql oracle11g pivot

我有一个查询,它返回以下表格中的结果:

Element  READING1  READING2 READING3
---------------------------------------
1        0.25      1.5      3.5
2        1.3       2.3      5.5
3        4.5       5.5      4.3
..        ..       ..       ..   
n        1.5       2.3      5.5
---------------------------------------

我希望以下列形式输出:

           1        2          3    ..     n
         ---------------------------------------
READING1  0.25     1.3        4.5   ..    1.5
READING2  1.5      2.3        5.5   ..    2.3
READING3  3.5      5.5        4.3   ..    5.5

,我必须转移表格。 我尝试过以下方式使用Oracle Pivot:

WITH T AS (
SELECT  Element,READING1 from ZZZ;    ----(1)
)
SELECT * FROM T
PIVOT( MAX(READING1) FOR ELEMENT IN (1,2,3,..n))     ----(2)

这只给了READING1的结果,但是我无法正确地产生所有读数的结果。任何帮助都将受到高度赞赏。

先谢谢,

最诚挚的问候, KUNAL

1 个答案:

答案 0 :(得分:2)

您已关闭 - 您想要的是UNPIVOTPIVOT的组合:

with T AS (
  select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
  select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
  select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual 
)
select * from (
  select * from t
  unpivot (reading_value
    for reading_name in ("READING1", "READING2", "READING3")
    )
  pivot(max(reading_value) for element in (1,2,3)
  )
)
order by reading_name

此查询

  • reading1,reading2,reading3转换为单独的(名称转换为 reading_name ,值转换为 reading_value < / em>的);这给了我们一行(element,reading_name)
  • 1,2 *,3(元素的值)转换为列&#39; 1&#39;,&#39; 2&#39 ;,&#39; 3&#39 ;;这给了我们每read_name一行

<强>更新

如果在运行时之前不知道元素列表(例如,因为用户可以选择它们),则需要更动态的方法。这是一个解决方案,它为给定的元素列表动态创建SQL语句,并为结果集使用sys_refcursor

-- setup table
create table T AS 
  select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
  select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
  select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual ;  
/

declare
  l_Elements dbms_sql.Number_Table;

  function pivot_it(p_Elements in dbms_sql.Number_Table) 
    return sys_refcursor is
      l_SQL CLOB := empty_clob();
      l_Result sys_refcursor;
    begin
      l_SQL := '
        select * from (
          select * from t 
            unpivot (reading_value
              for reading_name in ("READING1", "READING2", "READING3")
            )
          pivot(max(reading_value) for element in (';
      for i in 1 .. p_Elements.count
              loop
                  l_SQL := l_SQL || to_char(p_Elements(i)) || ',';
                end loop;
      -- remove trailing ','                
      l_SQL := regexp_replace(l_SQL, ',$');                
      l_SQL := l_SQL || ')
        )
      )';
      dbms_output.put_line(l_SQL);
      open l_Result for l_SQL;
      return l_Result;
  end;      
begin
  l_Elements(1) := 1;
  l_Elements(2) := 2;
  -- uncomment this line to get all 3 elements
  -- l_Elements(3) := 3;
  -- return the cursor into a bind variable (to be used in the host environment)
  :p_Cursor := pivot_it(l_Elements);  
end;

如何使用从此函数返回的光标取决于您使用的环境 - 在SQL / Plus中,您只需打印它,以及大多数编程语言&#39; Oracle绑定支持它开箱即用。

CAVEAT:虽然此代码适用于所提供的数据,但它甚至缺少基本的错误检查。这一点尤为重要,因为动态SQL始终是SQL注入攻击的可能目标。