Oracle line string is split into multiple lines

Test Data

--单条数据
with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
)
select * from z_branch;

insert image description here

--多条数据
with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
  union all
  select 'BR1002' brid, 'BR1002.BR1003' br_level from dual
  union all
  select 'BR1003' brid, 'BR1001.BR1003' br_level from dual
)
select * from z_branch;

insert image description here

1. Split a single string or a single piece of data

Can be used if there is only a single row of data in the table or to split a single string. Most of the talk on the Internet is about the splitting of a single piece of data, which is not applicable if it is splitting multiple pieces of data.

with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
)
select level, 
       regexp_count(br_level, '\.') + 1,
       regexp_substr(br_level, '[^.]+', 1, level) s_brid
  from z_branch t
connect by level <= regexp_count(br_level, '\.') + 1;

regexp_count(br_level, '.') counts the number of characters.
regexp_substr(br_level, '[^.]+', 1, level) The br_level field uses characters from position 1. Split, level refers to the first level after split string

or

with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
)
select level,
       length(brid) - length(replace(brid, '.', '')) + 1,
       regexp_substr(br_level, '[^.]+', 1, level) s_brid
  from z_branch t
connect by level <= length(br_level) - length(replace(br_level, '.', '')) + 1;

insert image description here
error example

--结果不符合预期
with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
  union all
  select 'BR1002' brid, 'BR1002.BR1003' br_level from dual
  union all
  select 'BR1003' brid, 'BR1001.BR1003' br_level from dual
)
select brid,
       level, 
       regexp_count(br_level, '\.') + 1,
       regexp_substr(br_level, '[^.]+', 1, level) s_brid
  from z_branch t
connect by level <= regexp_count(br_level, '\.') + 1;

insert image description here

-- 不符合预期
with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
  union all
  select 'BR1002' brid, 'BR1002.BR1003' br_level from dual
  union all
  select 'BR1003' brid, 'BR1001.BR1003' br_level from dual
)
select brid,
       level, 
       regexp_count(br_level, '\.') + 1,
       regexp_substr(br_level, '[^.]+', 1, level) s_brid
  from z_branch t
 where t.brid = 'BR1001'
connect by level <= regexp_count(br_level, '\.') + 1;

insert image description here
From the result, it can be seen that the data is generated first, and then filtered using the where condition

2. Multiple pieces of data splitting

1. Method 1

--正确
with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
  union all
  select 'BR1002' brid, 'BR1002.BR1003' br_level from dual
  union all
  select 'BR1003' brid, 'BR1001.BR1003' br_level from dual
)
select brid,
       level, 
       regexp_count(br_level, '\.') + 1 as row_cnt,
       regexp_substr(br_level, '[^.]+', 1, level) as s_brid
  from z_branch t
connect by level <= regexp_count(br_level, '\.') + 1
   and t.brid = prior t.brid
   and prior dbms_random.value > 0;

insert image description here

2. Method 2

--正确 借助伪列
with z_branch as(
  select 'BR1001' brid, 'BR1001.BR1002.BR1003' br_level from dual
  union all
  select 'BR1002' brid, 'BR1002.BR1003' br_level from dual
  union all
  select 'BR1003' brid, 'BR1001.BR1003' br_level from dual
),
z_level as(
  select level lv from dual connect by level < 10
) 
select t.brid,
       a.lv, 
       regexp_count(t.br_level, '\.') + 1 as row_cnt,
       regexp_substr(t.br_level, '[^.]+', 1, a.lv) as s_brid
  from z_branch t
 inner join z_level a
    on a.lv <= regexp_count(t.br_level, '\.') + 1;

insert image description here
Note: The number of pseudo-column rows created must be greater than the maximum number after string splitting. In this example, the maximum value after string splitting is 3, so as long as the number of pseudo-column rows is greater than 3.

Guess you like

Origin blog.csdn.net/u012132482/article/details/110582235