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

3-1 別テーブル優先の抽出

SQLパズル

Masterテーブル
Col1  Col2      Col3
----  --------  ------------
1     吉法師    尾張のうつけ
2     日吉      日輪の子
3     竹千代    今川の人質

Priorityテーブル
Col1  Col2      Col3
----  --------  ------
1     織田信長  右大臣
3     徳川家康  内府
4     明智光秀  日向守

MasterテーブルのCol1,Col2,Col3を取得する
ただし、MasterテーブルのCol1に紐づくレコードがPriorityテーブルに存在すれば
PriorityテーブルのCol1,Col2,Col3を取得する

Masterテーブル、Priorityテーブルのプライマリキーは、Col1とする

出力結果
Col1  Col2      Col3
----  --------  ------
1     織田信長  右大臣
2     日吉      日輪の子
3     徳川家康  内府


データ作成スクリプト

create table Master(
Col1 int,
Col2 varchar(8),
Col3 varchar(12),
primary key(Col1));

create table Priority(
Col1 int,
Col2 varchar(8),
Col3 varchar(12),
primary key(Col1));

insert into Master values
(1,'吉法師','尾張のうつけ'),
(2,'日吉','日輪の子'),
(3,'竹千代','今川の人質');

insert into Priority values
(1,'織田信長','右大臣'),
(3,'徳川家康','内府'),
(4,'明智光秀','日向守');


SQL

#■■■case式で分岐させる方法1■■■
select a.Col1,
case when b.Col1 is null then a.Col2 else b.Col2 end as Col2,
case when b.Col1 is null then a.Col3 else b.Col3 end as Col3
from Master a Left join Priority b
on a.Col1=b.Col1
order by Col1;

#■■■case式で分岐させる方法2■■■
select
case when exists(select 1 from Priority b where b.Col1=a.Col1)
     then  (select b.Col1 from Priority b where b.Col1=a.Col1)
     else Col1 end as Col1,
case when exists(select 1 from Priority b where b.Col1=a.Col1)
     then  (select b.Col2 from Priority b where b.Col1=a.Col1)
     else Col2 end as Col2,
case when exists(select 1 from Priority b where b.Col1=a.Col1)
     then  (select b.Col3 from Priority b where b.Col1=a.Col1)
     else Col3 end as Col3
from Master a
order by Col1;

#■■■unionを使用する方法■■■
select Col1,Col2,Col3 from Master a
where not exists(select 1 from Priority b
                  where b.Col1=a.Col1)
union all select Col1,Col2,Col3 from Priority b
where exists(select 1 from Master a
              where b.Col1=a.Col1)
order by Col1;


解説

外部結合してcase式で分岐させる方法や、
case when existsで分岐させる方法がありますが、
unionを使用する方法もあります

unionを使用する方法では、
MasterのCol1に紐づくレコードがPriorityに存在しなければ、最初のselect文が行を返し
MasterのCol1に紐づくレコードがPriorityに存在すれば、次のselect文が行を返す
クエリになっていて、
ブール代数の補元法則
 A + not(A) = 1
を使用してます