--■■■再帰with句を使う方法(11gR2以降)■■■
with tmp as(
select sortKey,Val,Row_Number() over(order by sortKey) as rn
from knapSackTable),
rec(rootSortKey,sortKey,rn,sumVal,maxDiff) as(
select sortKey,sortKey,rn,Val,0
from tmp
where Val < 9
union all
select a.rootSortKey,b.sortKey,b.rn,
a.sumVal+b.Val,greatest(a.maxDiff,b.sortKey-a.sortKey)
from rec a,tmp b
where a.rn+1=b.rn
and a.sumVal+b.Val < 9)
select rootSortKey,sortKey,sumVal,maxDiff
from (select rootSortKey,sortKey,sumVal,maxDiff,
max(sumVal) over() as maxSumVal
from rec)
where sumVal = maxSumVal
order by rootSortKey;
--■■■表関数を使う方法■■■
create or replace Package Pack10_336 Is
type PrintType is record(
rootSortKey knapSackTable.sortKey%type,
sortKey knapSackTable.sortKey%type,
sumVal number(2),
maxDiff number(2));
type PrintTypeSet is table of PrintType;
end;
/
create or replace function PrintR10336 return Pack10_336.PrintTypeSet PipeLined IS
outR Pack10_336.PrintType;
cursor cur is select sortKey,Val,Row_Number() over(order by sortKey) as rn from knapSackTable;
type saveDataDef is table of cur%rowType index by binary_integer;
saveData saveDataDef;
type InfoDef is record(
RowData cur%rowType,
rootSortKey knapSackTable.sortKey%type,
sumVal number(2),
maxDiff number(2)
);
stackP binary_integer := 0;
type StackClass is table of InfoDef index by binary_integer;
st StackClass;
priInfo InfoDef;
willPush InfoDef;
IsLeaf boolean;
procedure push(pInfoDef InfoDef) is
begin
st(stackP) := pInfoDef;
stackP := stackP+1;
end;
function pop return InfoDef is
begin
stackP := stackP-1;
return st(stackP);
end;
function IsEmpty return boolean is
begin
return stackP = 0;
end;
begin
open cur;
fetch cur bulk collect into saveData;
close cur;
--Start With句
for I in 1..saveData.Count Loop
if saveData(I).Val < 9 then
willPush.RowData.sortKey := saveData(I).sortKey;
willPush.RowData.Val := saveData(I).Val;
willPush.RowData.rn := saveData(I).rn;
willPush.rootSortKey := saveData(I).sortKey;
willPush.sumVal := saveData(I).Val;
willPush.maxDiff := 0;
push(willPush);
end if;
end Loop;
while (IsEmpty = false) loop
priInfo := pop();
IsLeaf := true;
-- connect by句
for I in 1..saveData.Count Loop
if priInfo.RowData.rn+1 = saveData(I).rn then
if priInfo.sumVal + saveData(I).Val < 9 then
willPush.RowData.sortKey := saveData(I).sortKey;
willPush.RowData.Val := saveData(I).Val;
willPush.RowData.rn := saveData(I).rn;
willPush.rootSortKey := priInfo.rootSortKey;
willPush.sumVal := priInfo.sumVal+saveData(I).Val;
willPush.maxDiff := greatest(priInfo.maxDiff,
saveData(I).sortKey
- priInfo.RowData.sortKey);
push(willPush);
IsLeaf := false;
end if;
end if;
end Loop;
--葉なら出力
if IsLeaf then
outR.rootSortKey := priInfo.rootSortKey;
outR.sortKey := priInfo.RowData.sortKey;
outR.sumVal := priInfo.sumVal;
outR.maxDiff := priInfo.maxDiff;
pipe row(outR);
end if;
end Loop;
end;
/
sho err
select rootSortKey,sortKey,sumVal,maxDiff
from (select rootSortKey,sortKey,sumVal,maxDiff,
max(sumVal) over() as maxSumVal
from table(PrintR10336))
where sumVal = maxSumVal;