现在有这样一个功能,可是没有思路,各位帮忙看下。
有张表假设只有一列,字段都是number型的,现在是知道最后的和是一个数,我想知道这个数都是哪几个字段求和出来的。
比如100,表中有几十个字段,其中这几个字段相加得100,现在找出是哪几个字段的和是100,
不知道我说的明白不明白,谢谢各位了。ps.可能第一字段+第三字段+第N字段=100 或第5字段=100 或第四字段+第五字段=100
谢谢了啊

解决方案 »

  1.   

    可能说的有点模糊,就像下面这张图。工资和是一个已知的数,比如总计1245,是有ID1+ID2出来的。现在要是一个新书2000,如何知道是由哪几个ID相加得来的呢?可能ID5+ID8或ID10+ID11+ID50?
      

  2.   

    这是一个利用 集合 实现的从1-9 九个数字中找出和为10的组合。可以参考这个实现你的需求:
    declare
      sum_target integer := 10; --和为10
      num_limit  integer := 9; --可用的数字为1-9
      type arr is table of integer index by binary_integer;
      result_arr  arr; --存放符合条件的数值的数值
      tmp_int     integer; --存放准备插入数组的数字
      sum_current integer := 0; --当前数组中数值的和
     
      --用来操作数组的存储过程,add_int:传入的数值; 
      --add_type: 0:将add_int替换最后一个节点;1:添加到新的节点;-1:删除最后一个节点
      procedure proc(add_int in integer, add_type in integer) is
      begin
        if add_type = 0 then
          sum_current := sum_current - result_arr(result_arr.last) + add_int;
          result_arr(result_arr.last) := add_int;
         
        elsif add_type = 1 then
          -- i:=i+1;
          sum_current := sum_current + add_int;
          result_arr(nvl(result_arr.last, 0) + 1) := add_int;
        elsif add_type = -1 then
          sum_current := sum_current - result_arr(result_arr.last);
          result_arr.delete(result_arr.last);
          --  i:=i-1;
        end if;
      end proc;
     
      --打印结果
      procedure print_res as
        result_str varchar2(32767); --存放要打印的结果字符串
      begin
        result_str := null;
        for x in 1 .. result_arr.last loop
          result_str := result_str || '+' || result_arr(x);
        end loop;
        dbms_output.put_line(substr(result_str, 2));
      end print_res;
     
    begin
      loop
        if sum_current = 0 then
          proc(1, 1);
        elsif sum_current < sum_target and
              result_arr(result_arr.last) < num_limit then
          tmp_int := result_arr(result_arr.last) + 1;
          proc(tmp_int, 1);
        else
          if sum_current = sum_target and
             result_arr(result_arr.last) <= num_limit then
            --打印结果
            print_res;
          end if;
          proc(null, -1);
          if result_arr.count = 0 then
            goto endflag;
          end if;
          tmp_int := result_arr(result_arr.last) + 1;
          proc(tmp_int, 0);
        end if;
      end loop;
      <<endflag>>
      null;
    end;
      

  3.   

    4楼的想法提醒了我,我也写了一个关于1到9等于10的组合,你也可以研究一下
    with t as
     (select 1 a from dual  union all
      select 2 a from dual  union all
      select 3 a from dual  union all
      select 4 a from dual  union all
      select 5 a from dual  union all
      select 6 a from dual  union all
      select 7 a from dual  union all
      select 8 a from dual  union all
      select 9 a from dual),
      t1 as (
      select t.*,
             dbms_aw.eval_number(substr(sys_connect_by_path(a, '+'), 2)) dd,
             substr(sys_connect_by_path(a, '+'), 2) cc
        from t
      connect by nocycle a > prior a 
      and level <=4
      )
            
      select * from t1 where dd =10
      

  4.   

    declare
      sum_target integer := 172; --和为10
      num_limit  integer := 0; --可用的数字为1-9
      type arr is table of integer index by binary_integer;
      result_arr  arr; --存放符合条件的数值的数值
      tmp_int     integer; --存放准备插入数组的数字
      sum_current integer := 0; --当前数组中数值的和
      sal_add_int integer :=0;
      sal_add_int1 integer :=0;
      vv integer :=0;
     
      --用来操作数组的存储过程,add_int:传入的数值; 
      --add_type: 0:将add_int替换最后一个节点;1:添加到新的节点;-1:删除最后一个节点
      procedure proc(add_int in integer, add_type in integer) is
      begin
        if add_type = 0 then
          vv := result_arr(result_arr.last);
          select sal into sal_add_int from t2 where id = vv;
          select sal into sal_add_int1 from t2 where id = add_int;
          sum_current := sum_current - sal_add_int + sal_add_int1;
          result_arr(result_arr.last) := add_int;
          vv:=0;
          sal_add_int :=0;
          sal_add_int1 :=0;
        elsif add_type = 1 then
          select sal into sal_add_int from t2 where id = add_int;
          sum_current := sum_current + sal_add_int;
          sal_add_int :=0;
          result_arr(nvl(result_arr.last, 0) + 1) := add_int;
        elsif add_type = -1 then
          vv := result_arr(result_arr.last);
          select sal into sal_add_int from t2 where id = vv;
          sum_current := sum_current - sal_add_int;
          result_arr.delete(result_arr.last);
          vv:=0;
          sal_add_int:=0;
        end if;
      end proc;
     
      --打印结果
      procedure print_res as
        result_str varchar2(32767); --存放要打印的结果字符串
      begin
        result_str := null;
        for x in 1 .. result_arr.last loop
          result_str := result_str || '+' || result_arr(x);
        end loop;
        dbms_output.put_line(substr(result_str, 2));
      end print_res;
     
    begin
      select count(*) into num_limit from t2;
      loop
        if sum_current = 0 then
          proc(1, 1);
        elsif sum_current < sum_target and
              result_arr(result_arr.last) < num_limit then
          tmp_int := result_arr(result_arr.last) + 1;
          proc(tmp_int, 1);
        else
          if sum_current = sum_target and
             result_arr(result_arr.last) <= num_limit then
            --打印结果
            print_res;
          end if;
          proc(null, -1);
          if result_arr.count = 0 then
            goto endflag;
          end if;
          tmp_int := result_arr(result_arr.last) + 1;
          proc(tmp_int, 0);
        end if;
      end loop;
      <<endflag>>
      null;
    end;
    大概写了一下,不过这个对源数据的格式有要求,需要 id 依据 sal 从小到大的顺序逐次增加(可以新增一列)。这是根据上面的那个改了一下,还有其他实现方式,懒得写了
      

  5.   

    好的,谢谢。其实就是把sal弄个集合出来,关键sal列的数没规律。而且这功能也不上线,就帮同事开发个过程,没月用下,放测试库上,他对账用,要不好几百条记录只能人工自己对