2014-12-02 126 views
1

移調查詢結果我有一個查詢返回了結果如下表:在Oracle 11g中

 
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數據透視用以下方式嘗試:

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

回答

0

你接近 - 你想要的是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 

這個查詢

  • co lumns reading1,reading2,reading3到單獨(名字進入reading_name,該值成reading_value);這爲我們提供了每(元件,reading_name)一行
  • 轉換 1,2 *,3(的值元件)爲列 '1', '2', '3';這給了我們每reading_name

UPDATE

一行如果元素列表不知道,直到運行時(例如,因爲用戶有選擇他們的選項),你需要一個更動態的方法。下面是一個解決方案,它爲給定的元素列表動態創建一條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 /加你可以直接打印出來,和大多數編程語言甲骨文綁定支持外的the-框。

CAVEAT:儘管此代碼適用於提供的數據,但它甚至缺少基本的錯誤檢查。這一點尤其重要,因爲動態SQL始終是SQL注入攻擊的可能目標。

+1

嗨,弗蘭克,感謝這工作:),你可以簡要解釋這是如何工作的?提前致謝。 – Kunal 2014-12-02 11:12:08

+0

嗨@Frank,感謝您的更新。查詢返回的元素數量不固定[1,2,3在上面添加]有一個困難。有什麼方法可以在「IN子句」中動態添加值?我嘗試使用LISTAGG(ELEMENTS,','),但是這不起作用。問候,Kunal。 – Kunal 2014-12-02 12:16:39

+0

@Kunal如果元素的數量是可變的,那麼必須使用動態SQL。今天我會試着用一個例子來更新我的答案。 – 2014-12-02 12:21:15