トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

3-38 Outer Union (外和集合演算)

SQLパズル

NameTable              AgeTable
ID  seq  Name          ID  seq  Age
--  ---  --------      --  ---  ---
 1    1  Oda            1    1   49
 1    2  Aketi          1    3   20
 2    1  Tokugawa       2    1   70
 2    2  Honda          2    4   30
 2    3  Sakai
 3    1  Toyotomi

下記のOuter Union (外和集合演算)を模倣する。
(2008/9/16現在、Outer Unionは、Oracle11gですら使えません)

select ID,Seq,Name from NameTable
Outer Union
select ID,Seq,Age  from NameTable

出力結果
ID  SEQ  Name       Age
--  ---  --------  ----
 1    1  Oda         49
 1    2  Aketi     null
 1    3  null        20
 2    1  Tokugawa    70
 2    2  Honda     null
 2    3  Sakai     null
 2    4  null        30
 3    1  Toyotomi  null


データ作成スクリプト

create table NameTable(
ID   number(2),
seq  number(2),
Name varchar2(8),
primary key (ID,Seq));

create table AgeTable(
ID  number(2),
seq number(2),
Age number(2),
primary key (ID,Seq));

insert all
into NameTable values(1,1,'Oda')
into AgeTable  values(1,1,49)
into NameTable values(1,2,'Aketi')
into AgeTable  values(1,3,20)
into NameTable values(2,1,'Tokugawa')
into AgeTable  values(2,1,70)
into NameTable values(2,2,'Honda')
into NameTable values(2,3,'Sakai')
into AgeTable  values(2,4,30)
into NameTable values(3,1,'Toyotomi')
select 1 from dual;
commit;


SQL

--■■■union allを使う方法■■■
select ID,seq,max(Name) as Name,max(age) as age
from (select ID,seq,Name         ,to_number(null) as age from NameTable union all
      select ID,seq,to_char(null),Age                  from AgeTable)
group by ID,seq
order by ID,seq;

--■■■完全外部結合を使う方法1■■■
select nvl(a.ID,b.ID) as ID,nvl(a.seq,b.seq) as seq,a.Name,b.Age
  from NameTable a full join AgeTable b
    on a.ID  = b.ID
   and a.seq = b.seq
order by ID,seq;

--■■■完全外部結合を使う方法2■■■
select ID,seq,a.Name,b.Age
  from NameTable a natural full join AgeTable b
order by ID,seq;


解説

完全外部結合を使う方法1がオススメです。
完全外部結合を使う方法2は、同じ名前の列がなかったらクロスジョインになりますし、
仕様変更にも弱いでしょう。

データベース概説(第4回)(PDF)