トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
10-340 最新の2レコード以上連続した期間を出力
SQLパズル
EventTable
dayC Val
---------- ---
2005-01-18 7
2005-01-25 18
2005-01-27 18
2005-01-29 18
2005-01-30 18
2005-07-22 5
2006-01-04 5
2006-06-20 10
2007-04-16 18 ←出力対象
2007-05-30 18 ←出力対象
2008-01-06 30
2009-02-22 18
最新の同じValが2レコード以上連続した期間を出力する。
出力結果
dayC Val
---------- ---
2007-04-16 18
2007-05-30 18
データ作成スクリプト
create table EventTable(dayC,Val) as
select date '2005-01-18', 7 from dual union
select date '2005-01-25',18 from dual union
select date '2005-01-27',18 from dual union
select date '2005-01-29',18 from dual union
select date '2005-01-30',18 from dual union
select date '2005-07-22', 5 from dual union
select date '2006-01-04', 5 from dual union
select date '2006-06-20',10 from dual union
select date '2007-04-16',18 from dual union
select date '2007-05-30',18 from dual union
select date '2008-01-06',30 from dual union
select date '2009-02-22',18 from dual;
SQL
--■■■分析関数を何度も使う方法■■■
select dayC,Val
from (select dayC,Val,GID,
max(GID) over() as maxGID
from (select dayC,Val,GID,
count(*) over(partition by GID) as cnt
from (select dayC,Val,
sum(willSum) over(order by dayC) as GID
from (select dayC,Val,
case when Val
= Lag(Val) over(order by dayC)
then 0 else 1 end as willSum
from EventTable)))
where cnt > 1)
where GID = maxGID;
--■■■旅人算メソッドとwith句を使う方法■■■
with tmp as(
select dayC,Val,
Row_Number() over(order by dayC)
-Row_Number() over(partition by Val
order by dayC) as gap
from EventTable)
select dayC,Val
from tmp
where (Val,gap)
= (select
max(Val) Keep(Dense_Rank Last order by max(dayC)),
max(gap) Keep(Dense_Rank Last order by max(dayC))
from tmp
group by Val,gap
having count(*) > 1);
解説
旅人算メソッドを使うかで試行錯誤しました。
ネストした集約関数を使って、かつ、Last関数を使えるのは知りませんでした。
集約関数の幅が広がりますね :-)
select deptno,sal
from scott.emp
order by 1,2;
deptno sal
------ ----
10 1300
10 2450
10 5000
20 800
20 1100
20 2975
20 3000
20 3000
30 950
30 1250
30 1250
30 1500
30 1600
30 2850
select avg(max(sal)) as nestAggUsage1,
max(deptno) Keep(Dense_Rank First order by max(sal)) as nestAggUsage2
from scott.emp
group by deptno;
nestAggUsage1 nestAggUsage2
------------- -------------
3616.6667 30
***********************************************************************
こんな最頻値の求め方も可能になりますね。
2-3-5 モード(最頻値)を取得
select max(Col1) Keep(Dense_Rank Last order by count(*)) as 最頻値,
max(count(*)) as 最頻値のレコード数
from 最頻値テーブル
group by Col1;
最頻値 最頻値のレコード数
------ ------------------
60 4