トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
10-321 再帰with句で行を分割
SQLパズル
OrderT
ID Val
--- ---
111 17
222 16
333 22
444 9
555 11
666 15
777 2
888 13
IDごとに、行を分割する。
ただし、分割時のValは最大で10とする。
出力結果
ID NewVal
--- ------
111 10
111 7
222 10
222 6
333 10
333 10
333 2
444 9
555 10
555 1
666 10
666 5
777 2
888 10
888 3
データ作成スクリプト
create table OrderT(ID,Val) as
select 111,17 from dual union
select 222,16 from dual union
select 333,22 from dual union
select 444, 9 from dual union
select 555,11 from dual union
select 666,15 from dual union
select 777, 2 from dual union
select 888,13 from dual;
SQL
--■■■再帰with句を使う方法(11gR2以降)■■■
with rec(ID,Val) as(
select ID,Val
from OrderT
union all
select ID,Val-10
from rec
where Val-10 > 0)
select ID,Least(Val,10) as Val from rec
order by ID,Val desc;
--■■■model句を使う方法(10g以降)■■■
select ID,newVal
from OrderT
model
partition by(ID)
dimension by(0 as soeji)
measures(Val,0 as newVal)
rules ITERATE (999) UNTIL ((ITERATION_NUMBER+1)*10 > Val[0])
(newVal[ITERATION_NUMBER] = Least(10,Val[0]-10*ITERATION_NUMBER))
order by ID,newVal desc;
--■■■連番表と内部結合させる方法■■■
select ID,Least(10,a.Val-10*(b.cnter-1)) as NewVal
from OrderT a
Join (select RowNum as cnter from dict) b
on ceil(a.Val/10) >= b.cnter
order by a.ID,NewVal desc;
解説
再帰with句を使う方法が分かりやすいと思いますねぇ