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

4-5 case式による他分岐

SQLパズル

テーブルA
Y  Z
-  -
1  1
1  2
1  3
2  4
2  5
2  6
3  7
3  8
3  9

テーブルB
Z  val1
-  -----------
1  テーブルB1
3  テーブルB3
5  テーブルB5

テーブルC
Z  val1
-  -----------
3  テーブルC3
5  テーブルC5

テーブルD
Z  val1
-  -----------
8  テーブルD8
9  テーブルD9

テーブルAがあり、Y,Zで構成されている。

列Yの値が
1の時、テーブルBと、列Zの値をキーとして外部結合する。
2の時、テーブルCと、列Zの値をキーとして外部結合する。
3の時、テーブルDと、列Zの値をキーとして外部結合する。

出力結果
Y  Z  VAL1
-  -  -----------
1  1  テーブルB1
1  2  null
1  3  テーブルB3
2  4  null
2  5  テーブルC5
2  6  null
3  7  null
3  8  テーブルD8
3  9  テーブルD9
こちらを参考にさせていただきました


データ作成スクリプト

create table テーブルA(
Y number(1),
Z number(1));

create table テーブルB(
Z number(1),
val1 varchar2(12));

create table テーブルC as select * from テーブルB;
create table テーブルD as select * from テーブルB;

insert into テーブルA(Y,Z) values(1,1);
insert into テーブルA(Y,Z) values(1,2);
insert into テーブルA(Y,Z) values(1,3);
insert into テーブルB(Z,val1) values(1,'テーブルB1');
insert into テーブルB(Z,val1) values(3,'テーブルB3');
insert into テーブルB(Z,val1) values(5,'テーブルB5');

insert into テーブルA(Y,Z) values(2,4);
insert into テーブルA(Y,Z) values(2,5);
insert into テーブルA(Y,Z) values(2,6);
insert into テーブルC(Z,val1) values(3,'テーブルC3');
insert into テーブルC(Z,val1) values(5,'テーブルC5');

insert into テーブルA(Y,Z) values(3,7);
insert into テーブルA(Y,Z) values(3,8);
insert into テーブルA(Y,Z) values(3,9);
insert into テーブルD(Z,val1) values(8,'テーブルD8');
insert into テーブルD(Z,val1) values(9,'テーブルD9');
commit;


SQL

--■■■case式による他分岐を使用する方法■■■
select Y,Z,
case Y
when 1 then (select b.val1 from テーブルB b where b.Z=a.Z)
when 2 then (select b.val1 from テーブルC b where b.Z=a.Z)
when 3 then (select b.val1 from テーブルD b where b.Z=a.Z) end as val1
from テーブルA a
order by Y,Z;

--■■■decode関数による他分岐を使用する方法■■■
select Y,Z,
decode(Y,1,(select b.val1 from テーブルB b where b.Z=a.Z),
         2,(select b.val1 from テーブルC b where b.Z=a.Z),
         3,(select b.val1 from テーブルD b where b.Z=a.Z)) as val1
from テーブルA a
order by Y,Z;

--■■■unionで和集合を作成する方法■■■
select a.Y,a.Z,b.val1 from テーブルA a,テーブルB b
 where a.Z=b.Z(+)
   and a.Y=1
union all select a.Y,a.Z,b.val1 from テーブルA a,テーブルC b
 where a.Z=b.Z(+)
   and a.Y=2
union all select a.Y,a.Z,b.val1 from テーブルA a,テーブルD b
 where a.Z=b.Z(+)
   and a.Y=3
union all select Y,Z,null
from テーブルA a
where Y not in(1,2,3) or Y is null
order by 1,2;

--■■■外部結合とcoalesce関数を使用する方法■■■
select a.Y,a.Z,coalesce(b.val1,c.val1,d.val1) as val1
from テーブルA a
Left join テーブルB b ON a.Y=1 AND b.Z=a.Z
Left join テーブルC c ON a.Y=2 AND c.Z=a.Z
Left join テーブルD d ON a.Y=3 AND d.Z=a.Z
order by a.Y,a.Z;


解説

case式による他分岐、decode関数による他分岐、
unionで和集合を作成する方法、外部結合とcoalesce関数を使用する方法などがありますが、
case式による他分岐が、最も可読性の高いSQLになると思います。

ただし、スカラー問い合わせで2行以上の行を返すとエラーとなるため
case式、およびdecode関数による他分岐は、
エンティティ間が、1対1もしくは、多対1の場合にしか使えません。
他の方法は1対1、多対1、1対多、多対多いずれの場合でも使えます。

switch制御
switch文を扱おう