【问题标题】:Split column to multiple rows将列拆分为多行
【发布时间】:2010-09-14 21:37:53
【问题描述】:

我有一个表格,其中有一列包含多个用逗号 (,) 分隔的值,我想将其拆分,以便将每个站点放在自己的行上,但前面的数字相同。

所以我的选择会来自这个输入

table Sitetable

Number             Site
952240             2-78,2-89                                                                                                                                                                      
952423             2-78,2-83,8-34

创建此输出

Number             Site
952240             2-78
952240             2-89
952423             2-78 
952423             2-83
952423             8-34

我发现了一些我认为可行但不行的东西..

select Number, substr(
    Site, 
    instr(','||Site,',',1,seq),
    instr(','||Site||',',',',1,seq+1) - instr(','||Site,',',1,seq)-1)  Site
from Sitetable,(select level seq from dual connect by level <= 100) seqgen
where instr(','||Site,',',1,seq+1) > 0

Edit2:我看到我实际上一直有一个部分工作选择(我是一个糟糕的测试人员:(),上面的工作但唯一的问题是它丢失了最后一个站点值但我会尝试工作有点那个..

Edit3:现在可以工作了

select Number, substr(
Site, 
instr(','||Site,',',1,seq),
instr(','||Site||',',',',1,seq+1) - instr(','||Site,',',1,seq)-1)  Site
from Sitetable,(select level seq from dual connect by level <= 100) seqgen
where instr(','||Site,',',1,seq) > 0

【问题讨论】:

标签: sql oracle oracle10g tokenize


【解决方案1】:

正确答案是。

select Number, substr(
Site, 
instr(','||Site,',',1,seq),
instr(','||Site||',',',',1,seq+1) - instr(','||Site,',',1,seq)-1)  Site
from Sitetable,(select level seq from dual connect by level <= 100) seqgen
where instr(','||Site,',',1,seq) > 0

【讨论】:

    【解决方案2】:

    你试过 Michael Sofaer 对How to best split csv strings in oracle 9i的回答吗

    create or replace function splitter_count(str in varchar2, delim in char) return int as
    val int;
    begin
      val := length(replace(str, delim, delim || ' '));
      return val - length(str); 
    end;
    
    create type token_list is varray(100) of varchar2(200);
    
    CREATE or replace function tokenize (str varchar2, delim char) return token_list as
    ret token_list;
    target int;
    i int;
    this_delim int;
    last_delim int;
    BEGIN
      ret := token_list();
      i := 1;
      last_delim := 0;
      target := splitter_count(str, delim);
      while i <= target
      loop
        ret.extend();
        this_delim := instr(str, delim, 1, i);
        ret(i):= substr(str, last_delim + 1, this_delim - last_delim -1);
        i := i + 1;
        last_delim := this_delim;
      end loop;
      ret.extend();
      ret(i):= substr(str, last_delim + 1);
      return ret;
    end;
    

    【讨论】:

      【解决方案3】:

      ------------创建结果表----------------------------- --------------

      创建表resulTable(

      cnumber,

      网站 varchar2(1000)

      );

      ------------创建拆分程序----------------------------- ---------

      /这里我用 s2ss78s 替换了数字,例如:2-78 以供使用
      DBMS_UTILITY.comma_to_table(对数字不起作用)
      /

      创建或替换过程 split_list_to_rows(num number,plist varchar2) as

      ptablen BINARY_INTEGER;

      ptab DBMS_UTILITY.uncl_array;

      开始

      DBMS_UTILITY.comma_to_table (

      list => replace(replace(CONCAT('s', plist),',',',s'),'-','ss'),

      tablen => ptablen,

      tab => ptab);

      FOR i IN 1 .. ptablen 循环

      insert INTO resulTable VALUES (num,replace(ltrim(ptab(i),'s'),'ss','-'));

      结束循环;

      结束;

      ------------PL/SQL 块为每一行执行过程--------

      开始

      for i in (select cnumber,Site from Sitetable)

      循环

      split_list_to_rows(i.cnumber,i.Site);

      结束循环;

      结束;

      ----------查看结果------ ----------------------

      从结果表中选择 *;

      【讨论】:

        【解决方案4】:

        我认为您的最大限制为 100 个逗号分隔值,这是不必要的,但在您的情况下可能无害。

        而不是

        from Sitetable,(select level seq from dual connect by level <= 100) 
        

        这应该适用于任意数量的值(级别受存在的最大逗号数限制)。

        from Sitetable,(select level seq from dual connect by level <=  (select max((LENGTH(site)-LENGTH(REPLACE(site,',', '' ))) + 1) from sitetable)
        

        【讨论】:

          【解决方案5】:

          使用交叉连接:

          选择编号,站点编号
          从站点表 CROSS APPLY STRING_SPLIT(Site, ',');

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-08-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-03-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多