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

5-51 グループの値を交換

SQLパズル

番号テーブル
NO  GroupNO
--  -------
 1        1
 2        1
 3        1
 4        2
 5        2
 6        3
 7        3

NOが2のレコードのGroupNOと、
NOが5のレコードのGroupNOを入れ替える。

更新結果
NO  GroupNO
--  -------
 1        2
 2        2
 3        2
 4        1
 5        1
 6        3
 7        3


データ作成スクリプト

create table 番号(
NO      number(1),
GroupNO number(1));

insert into 番号 values(1,1);
insert into 番号 values(2,1);
insert into 番号 values(3,1);
insert into 番号 values(4,2);
insert into 番号 values(5,2);
insert into 番号 values(6,3);
insert into 番号 values(7,3);
commit;


SQL

--■■■インラインビューを使わない方法■■■
update 番号 a
set GroupNO = case GroupNO
              when (select b.GroupNO from 番号 b
                     where b.NO = 2)
              then (select b.GroupNO from 番号 b
                     where b.NO = 5)
              else (select b.GroupNO from 番号 b
                     where b.NO = 2) end
where GroupNO in(select b.GroupNO from 番号 b
                  where b.NO in(2,5));

--■■■インラインビューを使う方法■■■
update (
select GroupNO,
case GroupNO
when (select b.GroupNO from 番号 b
       where b.NO = 2)
then (select b.GroupNO from 番号 b
       where b.NO = 5)
else (select b.GroupNO from 番号 b
       where b.NO = 2) end as WillGroupNO
  from 番号 a
 where GroupNO in(select b.GroupNO from 番号 b
                   where b.NO in(2,5)))
set GroupNO = WillGroupNO;

--■■■mergeを使う方法1(10g以降)■■■
merge into 番号 a
using (select RowID as Row_ID,GroupNO,
       max(decode(No,2,GroupNO)) over() as Val2,
       max(decode(No,5,GroupNO)) over() as Val5
         from 番号) b
   on (a.RowID = b.Row_ID)
when matched then
update set a.GroupNO = case a.GroupNO
                       when Val2 then Val5
                       when Val5 then Val2
                       else a.GroupNO end;

--■■■mergeを使う方法2(10g以降)■■■
merge into 番号 a
using (select RowID as Row_ID,GroupNO,
       max(decode(No,2,GroupNO)) over() as Val2,
       max(decode(No,5,GroupNO)) over() as Val5
         from 番号) b
   on (a.RowID = b.Row_ID and b.GroupNO in(Val2,Val5))
when matched then
update set a.GroupNO = case a.GroupNO
                       when Val2 then Val5
                       when Val5 then Val2 end;


解説

単純case式で、GroupNOの値に応じた値を取得してます。

■■■■■■■■■■■■■■■■■■■■■■■■
mergeを使う方法では、
マージのon句で指定した列はupdate不可なので
RowIDをon句で指定してます。