Oracle の行文字列が複数の行に分割されている

テストデータ

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

ここに画像の説明を挿入

--多条数据
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;

ここに画像の説明を挿入

1. 単一の文字列または単一のデータを分割する

テーブルにデータが 1 行しかない場合、または 1 つの文字列を分割する場合に使用できます。インターネット上の話題のほとんどは 1 つのデータの分割に関するものですが、複数のデータを分割する場合には当てはまりません。

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, '.')は文字数をカウントします。
regexp_substr(br_level, '[^.]+', 1, level) br_level フィールドは位置 1 からの文字を使用します。 Split、level は分割後の最初のレベルを指します。

また

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;

ここに画像の説明を挿入
エラーの例

--结果不符合预期
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;

ここに画像の説明を挿入

-- 不符合预期
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;

ここに画像の説明を挿入
結果から、データが最初に生成され、次に where 条件を使用してフィルタリングされたことがわかります。

2. 複数のデータの分割

1. 方法 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;

ここに画像の説明を挿入

2.方法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;

ここに画像の説明を挿入
注意: 作成される擬似列の行数は、文字列分割後の最大数より大きくなければなりません。この例では、擬似列の行数が 3 より大きい限り、文字列分割後の最大値は 3 です。

おすすめ

転載: blog.csdn.net/u012132482/article/details/110582235