SUBSTR 在 oracle 中添加值
SUBSTR to ADD value in oracle
我 table 的列在 Oracle DB 中具有以下格式的数据。
COL 1
abc,mno:EMP
xyz:EMP;tyu,opr:PROF
abc,mno:EMP;tyu,opr:PROF
我正在尝试将数据转换为以下格式
COL 1
abc:EMP;mno:EMP
xyz:EMP;tyu:PROF;opr:PROF
abc:EMP;mno:EMP;tyu:PROF;opr:PROF
基本上是尝试获取 : 之后和之前的所有内容;移动它用它代替逗号。
我尝试了一些 SUBSTR 和 LISTAGG,但没有得到任何值得分享的东西。
此致。
这是一种选择;阅读代码中的注释。
SQL> with test (id, col) as
2 -- sample data
3 (select 1, 'abc,mno:EMP' from dual union all
4 select 2, 'xyz:EMP;tyu,opr:PROF' from dual union all
5 select 3, 'abc,mno:EMP;tyu,opr:PROF' from dual
6 ),
7 temp as
8 -- split sample data to rows
9 (select id,
10 column_value cv,
11 regexp_substr(col, '[^;]+', 1, column_value) val
12 from test cross join
13 table(cast(multiset(select level from dual
14 connect by level <= regexp_count(col, ';') + 1
15 ) as sys.odcinumberlist))
16 )
17 -- finally, replace comma with a string that follows a colon sign
18 select id,
19 listagg(replace(val, ',', substr(val, instr(val, ':')) ||';'), ';') within group (order by cv) new_val
20 from temp
21 group by id
22 order by id;
ID NEW_VAL
---------- ----------------------------------------
1 abc:EMP;mno:EMP
2 xyz:EMP;tyu:PROF;opr:PROF
3 abc:EMP;mno:EMP;tyu:PROF;opr:PROF
SQL>
使用 littlefoot 的答案,如果我要使用交叉应用,我将不需要转换为多重集...
with test (id, col) as
-- sample data
(select 1, 'abc,mno:EMP' from dual union all
select 2, 'xyz:EMP;tyu,opr:PROF' from dual union all
select 3, 'abc,mno:EMP;tyu,opr:PROF' from dual
),
temp as
-- split sample data to rows
(select id,
column_value cv,
regexp_substr(col, '[^;]+', 1, column_value) val
from test
cross apply (select level as column_value
from dual
connect by level<= regexp_count(col, ';') + 1)
)
-- finally, replace comma with a string that follows a colon sign
select id,
listagg(replace(val, ',', substr(val, instr(val, ':')) ||';'), ';') within group (order by cv) new_val
from temp
group by id
order by id;
你不需要递归任何东西,只需要基本的正则表达式:如果模式总是 something,something2:someCode
(例如你在逗号前没有冒号),那么就足够了。
with test (id, col) as (
select 1, 'abc,mno:EMP' from dual union all
select 2, 'xyz:EMP;tyu,opr:PROF' from dual union all
select 3, 'abc,mno:EMP;tyu,opr:PROF' from dual union all
select 3, 'abc,mno:EMP;tyu,opr:PROF;something:QWE;something2:QWE' from dual
)
select
/*
Grab this groups:
1) Everything before the comma
2) Then everything before the colon
3) And then everything between the colon and a semicolon
Then place group 3 between 1 and 2
*/
trim(trailing ';' from regexp_replace(col || ';', '([^,]+),([^:]+):([^;]+)', ':;:')) as res
from test
| RES |
| :------------------------------------------------------------- |
| abc:EMP;mno:EMP |
| xyz:EMP;tyu:PROF;opr:PROF |
| abc:EMP;mno:EMP;tyu:PROF;opr:PROF |
| abc:EMP;mno:EMP;tyu:PROF;opr:PROF;something:QWE;something2:QWE |
db<>fiddle here
我 table 的列在 Oracle DB 中具有以下格式的数据。
COL 1 |
---|
abc,mno:EMP |
xyz:EMP;tyu,opr:PROF |
abc,mno:EMP;tyu,opr:PROF |
我正在尝试将数据转换为以下格式
COL 1 |
---|
abc:EMP;mno:EMP |
xyz:EMP;tyu:PROF;opr:PROF |
abc:EMP;mno:EMP;tyu:PROF;opr:PROF |
基本上是尝试获取 : 之后和之前的所有内容;移动它用它代替逗号。
我尝试了一些 SUBSTR 和 LISTAGG,但没有得到任何值得分享的东西。
此致。
这是一种选择;阅读代码中的注释。
SQL> with test (id, col) as
2 -- sample data
3 (select 1, 'abc,mno:EMP' from dual union all
4 select 2, 'xyz:EMP;tyu,opr:PROF' from dual union all
5 select 3, 'abc,mno:EMP;tyu,opr:PROF' from dual
6 ),
7 temp as
8 -- split sample data to rows
9 (select id,
10 column_value cv,
11 regexp_substr(col, '[^;]+', 1, column_value) val
12 from test cross join
13 table(cast(multiset(select level from dual
14 connect by level <= regexp_count(col, ';') + 1
15 ) as sys.odcinumberlist))
16 )
17 -- finally, replace comma with a string that follows a colon sign
18 select id,
19 listagg(replace(val, ',', substr(val, instr(val, ':')) ||';'), ';') within group (order by cv) new_val
20 from temp
21 group by id
22 order by id;
ID NEW_VAL
---------- ----------------------------------------
1 abc:EMP;mno:EMP
2 xyz:EMP;tyu:PROF;opr:PROF
3 abc:EMP;mno:EMP;tyu:PROF;opr:PROF
SQL>
使用 littlefoot 的答案,如果我要使用交叉应用,我将不需要转换为多重集...
with test (id, col) as
-- sample data
(select 1, 'abc,mno:EMP' from dual union all
select 2, 'xyz:EMP;tyu,opr:PROF' from dual union all
select 3, 'abc,mno:EMP;tyu,opr:PROF' from dual
),
temp as
-- split sample data to rows
(select id,
column_value cv,
regexp_substr(col, '[^;]+', 1, column_value) val
from test
cross apply (select level as column_value
from dual
connect by level<= regexp_count(col, ';') + 1)
)
-- finally, replace comma with a string that follows a colon sign
select id,
listagg(replace(val, ',', substr(val, instr(val, ':')) ||';'), ';') within group (order by cv) new_val
from temp
group by id
order by id;
你不需要递归任何东西,只需要基本的正则表达式:如果模式总是 something,something2:someCode
(例如你在逗号前没有冒号),那么就足够了。
with test (id, col) as ( select 1, 'abc,mno:EMP' from dual union all select 2, 'xyz:EMP;tyu,opr:PROF' from dual union all select 3, 'abc,mno:EMP;tyu,opr:PROF' from dual union all select 3, 'abc,mno:EMP;tyu,opr:PROF;something:QWE;something2:QWE' from dual ) select /* Grab this groups: 1) Everything before the comma 2) Then everything before the colon 3) And then everything between the colon and a semicolon Then place group 3 between 1 and 2 */ trim(trailing ';' from regexp_replace(col || ';', '([^,]+),([^:]+):([^;]+)', ':;:')) as res from test
| RES | | :------------------------------------------------------------- | | abc:EMP;mno:EMP | | xyz:EMP;tyu:PROF;opr:PROF | | abc:EMP;mno:EMP;tyu:PROF;opr:PROF | | abc:EMP;mno:EMP;tyu:PROF;opr:PROF;something:QWE;something2:QWE |
db<>fiddle here