トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
10-350 担当した期間をまとめる
SQLパズル
担当テーブル
ID Name StaD
-- ---- ----------
1 AAAA 2006-01-01
2 AAAA 2006-02-03
3 BBBB 2006-03-21
4 AAAA 2006-04-13
5 BBBB 2007-01-01
6 BBBB 2007-09-01
担当した期間を下記のようにまとめる
出力結果
ID Name StaD EndD
-- ---- ---------- ----------
1 AAAA 2006-01-01 2006-03-20
3 BBBB 2006-03-21 2006-04-12
4 AAAA 2006-04-13 2006-12-31
5 BBBB 2007-01-01 null
データ作成スクリプト
create table 担当テーブル(ID primary key,Name,StaD) as
select 1,'AAAA',date '2006-01-01' from dual union
select 2,'AAAA',date '2006-02-03' from dual union
select 3,'BBBB',date '2006-03-21' from dual union
select 4,'AAAA',date '2006-04-13' from dual union
select 5,'BBBB',date '2007-01-01' from dual union
select 6,'BBBB',date '2007-09-01' from dual;
SQL
ALTER SESSION SET NLS_DATE_FORMAT = 'yyyy-mm-dd';
--■■■旅人算メソッドを使わない方法■■■
with tmp as(
select ID,Name,StaD,
case when Name = Lag(Name) over(order by StaD)
then 0 else 1 end as IsStart
from 担当テーブル)
select ID,Name,StaD,
Lead(StaD) over(order by StaD) - 1 as EndD
from tmp
where IsStart = 1
order by StaD;
--■■■旅人算メソッドを使う方法■■■
with tmp as(
select ID,Name,StaD,
Row_Number() over( order by StaD)
-Row_Number() over(partition by Name order by StaD) as Dis
from 担当テーブル)
select min(ID),Name,min(StaD),
Lead(min(StaD)) over(order by min(StaD)) -1 as EndD
from tmp
group by Name,Dis
order by min(ID);
解説
最初に思いついたのは、旅人算メソッドを使う方法でしたが、
旅人算メソッドを使わないほうが優れてますね。
旅人算メソッドは、銀の弾丸ではないのです。