|
|
改一下nyfor的解法求最接近答案:
create or replace package hierarchy is
type strtabletype1 is table of varchar2(4000) index by binary_integer;
type strtabletype is table of strtabletype1 index by binary_integer;
strtable strtabletype;
type numtabletype1 is table of number index by binary_integer;
type numtabletype is table of numtabletype1 index by binary_integer;
numtable numtabletype;
function sys_connect_by_path(p_level in number,
p_value in varchar2,
p_delimiter in varchar2 default ',',
p_index IN NUMBER DEFAULT 1)
return varchar2;
function sys_sum_by_path(p_level in number, p_value in number,p_index IN NUMBER DEFAULT 1)
return number;
pragma restrict_references(sys_connect_by_path, wnds);
pragma restrict_references(sys_sum_by_path, wnds);
lv_target NUMBER;
lv_found NUMBER;
PROCEDURE reset(p_target IN NUMBER);
FUNCTION if_continue(p_level in number, p_value in number,p_index IN NUMBER DEFAULT 1)
return number;
end;
/
create or replace package body hierarchy is
ls_ret varchar2(4000);
ln_ret number;
function sys_connect_by_path(p_level in number,
p_value in varchar2,
p_delimiter in varchar2 default ',',
p_index IN NUMBER DEFAULT 1)
return varchar2 is
begin
strtable(p_index)(p_level) := p_value;
ls_ret := p_value;
for i in reverse 1 .. p_level - 1 loop
ls_ret := strtable(p_index)(i) || p_delimiter || ls_ret;
end loop;
return ls_ret;
end;
function sys_sum_by_path(p_level in number, p_value in number,p_index IN NUMBER DEFAULT 1)
return number is
begin
numtable(p_index)(p_level) := p_value;
ln_ret := p_value;
for i in reverse 1 .. p_level - 1 loop
ln_ret := numtable(p_index)(i) + ln_ret;
end loop;
return ln_ret;
end;
PROCEDURE reset(p_target IN NUMBER)
AS
BEGIN
lv_target := p_target;
lv_found := 0;
END reset;
FUNCTION if_continue(p_level in number, p_value in number,p_index IN NUMBER DEFAULT 1)
RETURN NUMBER
IS
lv_current NUMBER;
BEGIN
IF lv_found=1 THEN
RETURN 0;
END IF;
lv_current := sys_sum_by_path(p_level, p_value,p_index);
IF lv_current<lv_target THEN
RETURN 1;
ELSE
IF lv_current=lv_target THEN
lv_found :=1;
END IF;
RETURN 0;
END IF;
END if_continue;
end;
/
---- 运行SQL之前必须初始化,设入目标答案(注意每次运行之前都要设,因为涉及到全局标志的初始化。否则会有奇怪的答案):
EXEC hierarchy.reset(33);
select path,amounts,total_amount from (
select rownum rn,
sys_connect_by_path(id, ',') path,
hierarchy.sys_connect_by_path(level, amount, '+') amounts,
hierarchy.sys_sum_by_path(level, amount) total_amount
from t_money
connect by id > prior id
AND hierarchy.if_continue(level, amount)=1
order by abs(total_amount-33)
)
where rownum=1;
[ 本帖最后由 newkid 于 2009-9-1 03:12 编辑 ] |
|