将列拆分为多行

发布于 2024-09-19 12:04:23 字数 1275 浏览 5 评论 0原文

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

所以我的选择将从这个输入

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

编辑2:我看到我实际上一直有一个部分在工作选择(我是一个蹩脚的测试人员:(),上面一个有效,但唯一的问题是它丢失了最后一个站点值,但我会尝试对此进行一些工作..

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

I have table with a column that contains multiple values separated by comma (,) and would like to split it so I get earch Site on its own row but with the same Number in front.

So my select would from this input

table Sitetable

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

Create this output

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

I found something that I thought would work but nope..

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: I see that I have actually had a part working select all the time (I was a crappy tester :(), the above one works but the only problem is that it looses the last Site value but Ill try to work a bit on that..

Edit3: Now its working

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不语却知心 2024-09-26 12:04:23

正确答案是。

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

And the correct answer is.

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
梦里南柯 2024-09-26 12:04:23

您是否尝试过 Michael Sofaer 对 如何最好地拆分 csv 字符串的回答甲骨文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;

Did you Try Michael Sofaer's answer to 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;
瞳孔里扚悲伤 2024-09-26 12:04:23

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

创建表resulTable(

cnumber number,

Site varchar2(1000)

);

------------创建分割器过程-------------------------------- ------

/这里我将数字例如:2-78 替换为 s2ss78s 以便使用
DBMS_UTILITY.comma_to_table(不适用于数字)
/

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

ptablen BINARY_INTEGER;

ptab DBMS_UTILITY.uncl_array;

开始

DBMS_UTILITY.comma_to_table (

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

tablen => ptablen,

tab => ;

FOR i IN 1 .. ptablen 循环

插入结果表值 (num,replace(ltrim(ptab(i),'s'),'ss','-'));

结束循环;

结尾;

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

开始

i in (select cnumber,Site from Sitetable)

循环

split_list_to_rows(i.cnumber,i.Site);

结束循环;

结尾;

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

从结果表中选择*;

------------Create Result Table-------------------------------------------

create table resulTable(

cnumber number,

Site varchar2(1000)

);

------------Create Splitter Procedure--------------------------------------

/Here I replaced numbers for example: 2-78 by s2ss78s for using
DBMS_UTILITY.comma_to_table(it doesn't work on numbers)
/

create or replace procedure split_list_to_rows(num number,plist varchar2) as

ptablen BINARY_INTEGER;

ptab DBMS_UTILITY.uncl_array;

begin

DBMS_UTILITY.comma_to_table (

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

tablen => ptablen,

tab => ptab);

FOR i IN 1 .. ptablen LOOP

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

END LOOP;

END;

------------PL/SQL Block To Execute Procedure For Each Row-------------------

begin

for i in (select cnumber,Site from Sitetable)

loop

split_list_to_rows(i.cnumber,i.Site);

end loop;

end;

------------------------See The Result---------------------------------------

select * from resulTable;

吾家有女初长成 2024-09-26 12:04:23

我认为您的最大限制为 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)

I think you have a max limit of 100 comma separated values which is unnecessary, though probably not harmful in your case.

instead of

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

this should work for any number of values (level limited by the max number of commas present).

from Sitetable,(select level seq from dual connect by level <=  (select max((LENGTH(site)-LENGTH(REPLACE(site,',', '' ))) + 1) from sitetable)
神经暖 2024-09-26 12:04:23

使用交叉联接:

SELECT Number、SiteNumber
来自网站表
交叉应用 STRING_SPLIT(站点, ',');

Use cross join:

SELECT Number, SiteNumber
FROM Sitetable
CROSS APPLY STRING_SPLIT(Site, ',');

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文