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

3-7 空き時間を探索してupdate

SQLパズル

TimeTableの、IDが9の列のVal1(Date型)を、2005年8月1日16時20分を第一候補とした時間に更新する
ただし同一時刻の登録データは3件までとし、
既に3件のデータが存在した場合は、10分後の時刻を次の候補として処理を再帰的に行う

データ作成スクリプト

create table TimeTable(
ID number(1),
Val1 date,
primary key(ID));

insert into TimeTable values(1,to_date('2005/08/01 16:10','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(2,to_date('2005/08/01 16:20','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(3,to_date('2005/08/01 16:20','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(4,to_date('2005/08/01 16:20','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(5,to_date('2005/08/01 16:30','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(6,to_date('2005/08/01 16:30','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(7,to_date('2005/08/01 16:30','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(8,to_date('2005/08/01 16:40','YYYY/MM/DD HH24;MI'));
insert into TimeTable values(9,to_date('2005/08/01 17:00','YYYY/MM/DD HH24;MI'));
commit;


SQL

update TimeTable myself
set Val1 =
case when (select count(a.Val1) from TimeTable a
            where a.RowID!=myself.RowID
              and a.Val1= to_date('2005/08/01 16:20','YYYY/MM/DD HH24;MI')
              and RowNum <= 3) < 3
     then to_date('2005/08/01 16:20','YYYY/MM/DD HH24;MI')
     else (select min(a.Val1) + 10/24/60 from TimeTable a
            where a.Val1 >= to_date('2005/08/01 16:20','YYYY/MM/DD HH24;MI')
              and (select count(b.Val1) from TimeTable b
                    where b.RowID!=myself.RowID
                      and b.Val1=a.Val1 + 10/24/60
                      and RowNum <= 3) < 3)
     end
where ID = 9;


解説

第一候補の時間に更新可能かを調べて、
更新可能の場合は、その時間となります

第一候補の時間に更新不可の場合は、Val1が最大のデータを番兵とした、
第一候補以降で更新可能な時間の探索を行います
(RowIDを比較して更新前のレコードを探索対象となる集合から外します)