2013-02-28 107 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