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

10-314 複数条件で、開始と終了をまとめる

SQLパズル

findBreakテーブル
staD        endD        Val
----------  ----------  ---
2009-06-22  2009-06-25  9
2009-06-25  2009-06-26  9
2009-06-27  2009-06-28  5
2009-06-28  2009-06-29  9
2009-10-10  2009-10-11  1
2009-10-11  2009-10-12  1
2009-10-12  2009-10-13  1
2009-10-13  2009-10-14  2
2009-10-14  2009-10-15  2
2009-10-15  2009-10-16  2
2009-10-16  2009-10-17  1
2009-10-17  2009-10-18  1
2009-10-18  2009-10-19  3
2009-10-19  2009-10-20  3
2009-11-20  2009-11-21  1
2009-11-21  2009-11-22  1
2009-11-22  2009-11-23  5
2009-11-23  2009-11-24  5
2009-11-24  2009-11-25  5

staDの昇順で、前の行のendDとstaDが一致して、かつ、
staDの昇順で、前の行のValとValが一致している行の
開始と終了をまとめて表示する。

出力結果
staD      endD      Val
--------  --------  ---
09-06-22  09-06-26    9
09-06-27  09-06-28    5
09-06-28  09-06-29    9
09-10-10  09-10-13    1
09-10-13  09-10-16    2
09-10-16  09-10-18    1
09-10-18  09-10-20    3
09-11-20  09-11-22    1
09-11-22  09-11-25    5

こちらを参考にさせていただきました(英語)


データ作成スクリプト

create table findBreak(staD,endD,Val) as
select date '2009-06-22',date '2009-06-25',9 from dual union all
select date '2009-06-25',date '2009-06-26',9 from dual union all
select date '2009-06-27',date '2009-06-28',5 from dual union all
select date '2009-06-28',date '2009-06-29',9 from dual union all
select date '2009-10-10',date '2009-10-11',1 from dual union all
select date '2009-10-11',date '2009-10-12',1 from dual union all
select date '2009-10-12',date '2009-10-13',1 from dual union all
select date '2009-10-13',date '2009-10-14',2 from dual union all
select date '2009-10-14',date '2009-10-15',2 from dual union all
select date '2009-10-15',date '2009-10-16',2 from dual union all
select date '2009-10-16',date '2009-10-17',1 from dual union all
select date '2009-10-17',date '2009-10-18',1 from dual union all
select date '2009-10-18',date '2009-10-19',3 from dual union all
select date '2009-10-19',date '2009-10-20',3 from dual union all
select date '2009-11-20',date '2009-11-21',1 from dual union all
select date '2009-11-21',date '2009-11-22',1 from dual union all
select date '2009-11-22',date '2009-11-23',5 from dual union all
select date '2009-11-23',date '2009-11-24',5 from dual union all
select date '2009-11-24',date '2009-11-25',5 from dual;


SQL

select min(staD) as staD,max(endD) as endD,Val
from (select staD,endD,Val,
      sum(willSum) over(order by staD) as GID
      from (select staD,endD,Val,
            case when staD
                    = Lag(endD) over(partition by Val order by staD)
                 then 0 else 1 end as willSum
              from findBreak))
group by Val,GID
order by staD;


解説

脳内のイメージにおいて、
staDの昇順でソートされた状態で、partition by Valで赤線を引いている
珍しいケースですねぇ