CREATE OR REPLACE FUNCTION SPLIT (p_list VARCHAR2, p_sep VARCHAR2 := ',')
   RETURN type_split PIPELINED
IS
   l_idx    PLS_INTEGER;
   v_list   VARCHAR2 (50) := p_list;
BEGIN
   LOOP
      l_idx := INSTR (v_list, p_sep);      IF l_idx > 0
      THEN
         PIPE ROW (SUBSTR (v_list, 1, l_idx - 1));
         v_list := SUBSTR (v_list, l_idx + LENGTH (p_sep));
      ELSE
         PIPE ROW (v_list);
         EXIT;
      END IF;
   END LOOP;   RETURN;
END SPLIT;
select * from table(split('bb','aa'));
返回的是一个表的2条数据 bb aa不过该函数貌似不能解决下面的问题
如表 A 中a字段存了总金额99,userid 字段中存了aa,22,bb 这样的用户id数据,我要把金额平均分配给每个人
A
id userid  je
-------
1 aa,22,bb 99
2 dd2,3a   2
........
我如何才能将该数据变成  
id userid je
1 aa  33
1 22  33
1 bb  33
2 dd2 1
2 3a  1
........
别说表不合理,因为为了减少数据量 userid中的用户数可能会10几个, 试试看这样的性能如何

解决方案 »

  1.   

    这个仅仅用sql好像不是很好搞,
    就是针对一条记录拆开也要做一个插入一个删除共两个操作吧
      

  2.   

    直接用sql很难搞,给你写了个procedure,直接输出结果:
    create or replace procedure pro_split as
      cu       sys_refcursor;
      arow     a%rowtype;
      v_userid varchar2(20);  n            number;
      v_user_idout varchar2(20);
    begin
      open cu for
        select * from a;
      loop
        fetch cu
          into arow;
        exit when cu%notfound;
        n        := 1;
        v_userid := arow.userid;
        while instr(v_userid, ',') > 0 loop
        
          v_userid := substr(v_userid, instr(v_userid, ',') + 1);
          n        := n + 1;
        end loop;
        v_userid := arow.userid;
        while instr(v_userid, ',') > 0 loop
        
          v_user_idout := substr(v_userid, 1, instr(v_userid, ',') - 1);
          v_userid     := substr(v_userid, instr(v_userid, ',') + 1);
          dbms_output.put_line(arow.id || '     ' || v_user_idout || '    ' ||
                               (arow.je / n));
        end loop;
        dbms_output.put_line(arow.id || '     ' || v_userid || '    ' ||
                             (arow.je / n));
      end loop;
    end;
    SQL> exec pro_split;
     
    1     aa    33
    1     22    33
    1     bb    33
    2     dd2    1
    2     3a    1
     
    PL/SQL procedure successfully completed
      

  3.   


    /*
    SQL> drop table a;Table droppedSQL> create table A (id int,userid varchar2(20), je int);Table createdSQL> insert into A values(1,'aa,22,bb',99);1 row insertedSQL> insert into A values(2,'dd2,3a',2);1 row insertedSQL> commit;Commit complete  */SQL> select * from A;          ID USERID            JE
    ------------ ---------------   ----------
               1        aa,22,bb   99
               2          dd2,3a   2
     
    SQL> select id,userid,je/(count(1) over(partition by id)) as je
      2    from (
      3  select id,substr(',' || userid || ',',
      4                instr(',' || userid || ',', ',', 1, rn) + 1,
      5                instr(',' || userid || ',', ',', 1, rn + 1) -
      6                instr(',' || userid || ',', ',', 1, rn) - 1) as userid,
      7         je
      8    from A,
      9         (select rownum rn
     10            from all_objects
     11           where rownum <= (select max(length(userid) -
     12                                       length(replace(userid, ',')) + 1)
     13                              from A)))
     14    where userid is not null
     15  /            ID USERID         JE
    -------------- ------------   ----------
                 1           aa   33
                 1           22   33
                 1           bb   33
                 2          dd2    1
                 2           3a    1SQL> 
      

  4.   

    TO:mantisXF(枫の叶)
    哈哈,反正你没申请版权,被我学习了.
      

  5.   

    exec pro_split;
     
    1     aa    33
    1     22    33
    1     bb    33
    2     dd2    1
    2     3a    1
     
    PL/SQL procedure successfully completed