2016-03-03 64 views
1

我试图找到合并2个表和透视的方法。需要注意的是,我使用的是oracle 9i版本,显然没有pivot功能。所以我希望我能解决这个问题。我有2个表有以下形式:版本9i中的Oracle SQL组合表和数据透视

人表:

ID NAME 
1 John 
2 Steve 
3 Bob 
4 Gary 

电话号码表:

ID TYPE NUMBER 
1 1 555-5555 
2 1 555-5556 
2 2 555-5557 
3 2 555-5558 
4 5 555-5559 

而且我希望能够加入表如下:

ID NAME NUMBER_1 NUMBER_2 
1 John 555-5555 
2 Steve 555-5556 555-5557 
3 Bob    555-5558 
4 Gary 

请注意,有一些不同的TYPE值,但我只关心1 a ND 2.

目前的解决方案,我现在已经是加入对ID表和使用CASE语句调理上TYPE产生NUMBER_1NUMBER_2。问题是,如果我加入表格,那么Steve会有2行。

+0

会不会是永远两个''每Name' –

+0

Number's'在电话号码表中会有每个ID不一定是2个数字。可能是0,1,2,2+。在结果表中,我只关心这些人的两种电话号码(他们对应于手机#和家庭# - 我不在乎传真#等) –

回答

1

您可以使用conditional aggregation模仿pivot,因为你只在乎1型和2:

select p.id, 
    p.name, 
    max(case when pn.type = 1 then pn.number end) number_1, 
    max(case when pn.type = 2 then pn.number end) number_2 
from person p 
    left join phonenumber pn on p.id = pn.id 
     and pn.type in (1,2) 
group by p.id, p.name 

如果null结果是一个问题,使用outer join代替。 (阅读你的意见,他们是,所以我更新了答案)。如果您不想让没有电话号码的人返回,请将其更改回inner join

注意:使用group by可确保您每人只能收到一行。 conditional aggregation将允许您返回家庭和手机号码。


每在您的评论你的关心,这可以包括作为一个子查询这样:

select * 
from sometable s 
    join (
     select p.id, 
      p.name, 
      max(case when pn.type = 1 then pn.number end) number_1, 
      max(case when pn.type = 2 then pn.number end) number_2 
     from person p 
      left join phonenumber pn on p.id = pn.id 
       and pn.type in (1,2) 
     group by p.id, p.name 
    ) t on t.id = s.id 
+0

我加入的实际表格有一吨列。有没有办法让每个人得到1行,而不必明确地按照我的表中的每个变量进行“分组”? –

+0

@divide_by_zero - 使用聚合时,您在'select'列表中返回的任何未包含在聚合函数中的字段必须包含在'group by'子句中。你可以使用'动态sql'来为你生成列表,但我建议你输入它们。或者,您可以将它移动到只有id和电话号码的“子查询”,然后“加入”到其他表格 - 这样您就不必列出其他字段。 – sgeddes

+0

@divide_by_zero - 用子查询的例子更新了答案... – sgeddes