2013-02-28 80 views
1

我正在嘗試爲一個新表準備數據,這個數據表是來自現有表的相同數據,但是是非規範化的。我有一個簡單的場景,但我的心是在返回的結果Oracle SQL查詢非規範化

它是基於以下簡化方案的最有效的方法一片空白:

Table X | Table y 
id  | id Identifier Value 
123  | 123 1   A 
      | 123 2   B 

隨着從表XI其它字段需要我查詢返回:

123 A B 

我已經考慮:

解決方案一

select 
id, 
(select Value...), 
(select Value...)... 

解決方案二:

select id, 
y1.Value, 
y2.Value 
from x, y y1, y y2... 

解決方案三:利用PL/SQL和通過遊標

解四迭代 : 提取Y考慮identifyer1和identifier2(潛在使用觸發器)兩個表,並加入查詢中的那些表,而不是

這些解決方案都有一個主要缺點,出於某種原因,我確信有一個詞可以讓我想起一個公司除了解決這個問題

+0

通過你的輸出例子來看,你必須在表Y.所有的信息或者你可以通過ID加入X和Y使用Listagg()或WM_Concat(10g)來連接來自表Y的值,而不是透視。不需要PL/SQL。 – Art 2013-02-28 21:49:37

回答

5

除非我失去了一些東西,你正在嘗試樞軸的數據。有幾種方法可以做到這一點。

您可以使用聚合函數和CASE表達:

select x.id, 
    max(case when y.identifier = 1 then y.value end) Value1, 
    max(case when y.identifier = 2 then y.value end) Value2 
from tablex x 
left join tabley y 
    on x.id = y.id 
group by x.id 

SQL Fiddle with Demo

根據您的Oracle版本,你可以使用PIVOT功能:

select id, 
    Value1, 
    Value2 
from 
(
    select x.id, y.identifier, y.value 
    from tablex x 
    left join tabley y 
    on x.id = y.id 
) 
pivot 
(
    max(value) 
    for identifier in ('1' as Value1, '2' as Value2) 
) piv 

SQL Fiddle with Demo

你可以參加多次:

select x.id, 
    y1.value Value1, 
    y2.value Value2 
from tablex x 
left join tabley y1 
    on x.id = y1.id 
    and y1.identifier = 1 
left join tabley y2 
    on x.id = y2.id 
    and y2.identifier = 2 

SQL Fiddle with Demo

如果你正在尋找一個動態的解決方案,那麼你可以使用SYS_REFCURSOR創建一個過程:

CREATE OR REPLACE procedure dynamic_pivot(p_cursor in out sys_refcursor) 
as 
    sql_query varchar2(8000) := 'select x.id '; 

    begin 
     for x in (select distinct identifier from tabley order by 1) 
     loop 
      sql_query := sql_query || 
       ' , max(case when y.identifier = '||x.identifier||' then y.value else null end) as Value'||x.identifier; 

       dbms_output.put_line(sql_query); 
     end loop; 

     sql_query := sql_query || ' from tablex x 
            left join tabley y 
             on x.id = y.id 
            group by x.id'; 
     dbms_output.put_line(sql_query); 

     open p_cursor for sql_query; 
    end; 
/

這些解決方案讓您在每個值單獨列的結果。如果你想在一列中的數據,那麼你可以使用LISTAGG()

select x.id, 
    listagg(y.value, ' ') within group (order by y.id) as Value 
from tablex x 
left join tabley y 
    on x.id = y.id 
group by x.id 

SQL Fiddle with Demo

+0

我想他想要一個任意大小的數據透視表(這在SQL Server中使用as XML技巧很容易)。 – Hogan 2013-02-28 20:47:58

+0

@Hogan更新爲包含動態解決方案。 – Taryn 2013-02-28 20:58:49

+0

不錯,現在我知道怎麼在oracle上做 – Hogan 2013-02-28 21:21:17