これは本当に悪いデザインであることに同意します。そのデザインを変更できない場合は、これを試してください:
select distinct id, trim(regexp_substr(value,'[^,]+', 1, level) ) value, level
from tbl1
connect by regexp_substr(value, '[^,]+', 1, level) is not null
order by id, level;
OUPUT
id value level
1 AA 1
1 UT 2
1 BT 3
1 SK 4
1 SX 5
2 AA 1
2 UT 2
2 SX 3
3 UT 1
3 SK 2
3 SX 3
3 ZF 4
これへのクレジット
よりエレガントで効率的な方法で重複を削除するには(@mathguyのクレジット)
select id, trim(regexp_substr(value,'[^,]+', 1, level) ) value, level
from tbl1
connect by regexp_substr(value, '[^,]+', 1, level) is not null
and PRIOR id = id
and PRIOR SYS_GUID() is not null
order by id, level;
「ANSIer」アプローチが必要な場合は、CTEを使用してください:
with t (id,res,val,lev) as (
select id, trim(regexp_substr(value,'[^,]+', 1, 1 )) res, value as val, 1 as lev
from tbl1
where regexp_substr(value, '[^,]+', 1, 1) is not null
union all
select id, trim(regexp_substr(val,'[^,]+', 1, lev+1) ) res, val, lev+1 as lev
from t
where regexp_substr(val, '[^,]+', 1, lev+1) is not null
)
select id, res,lev
from t
order by id, lev;
出力
id val lev
1 AA 1
1 UT 2
1 BT 3
1 SK 4
1 SX 5
2 AA 1
2 UT 2
2 SX 3
3 UT 1
3 SK 2
3 SX 3
3 ZF 4
MT0による別の再帰的アプローチですが、正規表現はありません:
WITH t ( id, value, start_pos, end_pos ) AS
( SELECT id, value, 1, INSTR( value, ',' ) FROM tbl1
UNION ALL
SELECT id,
value,
end_pos + 1,
INSTR( value, ',', end_pos + 1 )
FROM t
WHERE end_pos > 0
)
SELECT id,
SUBSTR( value, start_pos, DECODE( end_pos, 0, LENGTH( value ) + 1, end_pos ) - start_pos ) AS value
FROM t
ORDER BY id,
start_pos;
30000行のデータセットで3つのアプローチを試し、118104行が返され、次の平均結果が得られました。
- 私の再帰的アプローチ:5秒
- MT0アプローチ:4秒
- マスガイアプローチ:16秒
- MT0再帰的アプローチの正規表現なし:3.45秒
@Mathguyは、より大きなデータセットでもテストしました:
すべての場合において、再帰クエリ(regularsubstrとinstrを使用したクエリのみをテストしました)の方が2〜5倍優れています。これは、文字列あたりの文字列/トークンの数と、階層型と再帰型、階層型のCTAS実行時間の組み合わせです。 。常に秒単位
- 30,000 x 4:5/1。
- 30,000 x 10:15/3。
- 30,000 x 25:56/37。
- 5,000 x 50:33/14。
- 5,000 x 100:160/81。
- 10,000 x 200:1,924 / 772