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

10-328 連続した3日のセットを出力できるだけ出力

SQLパズル

daysTable
ID  dt
--  ----------
11  2010-06-07
11  2010-06-06
11  2010-06-05
11  2010-06-03
11  2010-06-02
11  2010-06-01
22  2010-11-17
22  2010-11-16
22  2010-11-15
22  2010-11-14
22  2010-11-13
22  2010-11-12
22  2010-11-09
33  2010-12-07
33  2010-12-06
33  2010-12-04

IDごとで最大の日から、連続した3日のセットを出力できるだけ出力する。

出力結果
ID  dt
--  ----------
11  2010-06-07
11  2010-06-06
11  2010-06-05
22  2010-11-17
22  2010-11-16
22  2010-11-15
22  2010-11-14
22  2010-11-13
22  2010-11-12

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


データ作成スクリプト

create table daysTable(ID,dt) as
select 11,date '2010-06-07' from dual union all
select 11,date '2010-06-06' from dual union all
select 11,date '2010-06-05' from dual union all
select 11,date '2010-06-03' from dual union all
select 11,date '2010-06-02' from dual union all
select 11,date '2010-06-01' from dual union all
select 22,date '2010-11-17' from dual union all
select 22,date '2010-11-16' from dual union all
select 22,date '2010-11-15' from dual union all
select 22,date '2010-11-14' from dual union all
select 22,date '2010-11-13' from dual union all
select 22,date '2010-11-12' from dual union all
select 22,date '2010-11-09' from dual union all
select 33,date '2010-12-07' from dual union all
select 33,date '2010-12-06' from dual union all
select 33,date '2010-12-04' from dual;


SQL

select ID,dt
from (select ID,dt,
      max(dt) over(partition by ID) as maxdt,
      count(dt) over(partition by ID order by dt range 2 preceding) as has3
        from daysTable)
start with dt = maxdt
       and has3 = 3
connect by prior dt-1=dt
       and prior ID=ID
       and not(mod(Level-1,3)=0 and has3!=3);


解説

まず、インラインビューで、
分析関数で木の根となるノードや、
3日連続しているかをrange指定の分析関数で求めてます。

次に、階層問い合わせで、3日連続しているかを枝切り条件として使ってます。