トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
5-65 連続した期間の抽出(OverLapを考慮せず)
SQLパズル
kikanT
ID StaD EndD
-- ---------- ----------
10 2010-06-01 2010-06-12
10 2010-06-13 2010-06-14
10 2010-06-15 null
20 2010-06-01 2010-06-11
20 2010-06-13 2010-06-15
50 2010-11-11 2010-11-13
50 2010-11-14 2010-11-20
50 2010-12-22 2010-12-30
IDごとで連続した期間をまとめる。
同じIDでの期間のOverLapは、存在しないものとする。
出力結果
ID StaD EndD
-- ---------- ----------
10 2010-06-01 null
20 2010-06-01 2010-06-11
20 2010-06-13 2010-06-15
50 2010-11-11 2010-11-20
50 2010-12-22 2010-12-30
データ作成スクリプト
create table kikanT(ID,StaD,EndD) as
select 10,date '2010-06-01',date '2010-06-12' from dual union
select 10,date '2010-06-13',date '2010-06-14' from dual union
select 10,date '2010-06-15',null from dual union
select 20,date '2010-06-01',date '2010-06-11' from dual union
select 20,date '2010-06-13',date '2010-06-15' from dual union
select 50,date '2010-11-11',date '2010-11-13' from dual union
select 50,date '2010-11-14',date '2010-11-20' from dual union
select 50,date '2010-12-22',date '2010-12-30' from dual;
SQL
--■■■階層問い合わせを使う方法(10g以降)■■■
select ID,min(connect_by_root StaD) as StaD,EndD
from kikanT
where connect_by_IsLeaf = 1
connect by prior ID=ID
and prior EndD+1=StaD
group by ID,EndD
order by ID,EndD;
--■■■分析関数を使う方法■■■
select ID,min(StaD) as StaD,
max(EndD) Keep(Dense_Rank Last order by EndD) as EndD
from (select ID,StaD,EndD,
sum(willSum) over(partition by ID order by StaD) as GID
from (select ID,StaD,EndD,
case when StaD = 1+Lag(EndD) over(partition by ID order by StaD)
then 0 else 1 end as willSum
from kikanT))
group by ID,GID
order by ID,GID;
解説