形式のデータがあります
データ
column1 column2
abcd ~123~abd~
列 2 のデータは ~ で区切られています
出力は 2 行の形式である必要があります
column1 column2
abcd 123
abcd abd
助けてください。
形式のデータがあります
データ
column1 column2
abcd ~123~abd~
列 2 のデータは ~ で区切られています
出力は 2 行の形式である必要があります
column1 column2
abcd 123
abcd abd
助けてください。
Oracle には組み込みの文字列トークナイザーはありませんが、独自に構築するのは簡単です。いくつかの異なるソリューションがあります (SO とより広いインターウェブの両方で) が、関数を使用しstring_tokenizer()
ます。
with data as ( select column1
, trim(both '~' from column2) as column2
from your_table )
select data.column1
, t.column_value
from data
, table ( string_tokenizer (data.column2, '~'))t;
ちなみに、 TRIM() 呼び出しは、の先頭と末尾のインスタンスを削除するために必要です~
(ただし、代わりにトークナイザー関数がそれを処理できるかもしれませんが.うーん...)
サンプルデータを
SQL> select * from your_table;
COLUMN1 COLUMN2
-------------------- --------------------
abcd ~123~abd~
foo ~test~test2~
foo2 ~test~
モデル条項 (10g+):
SQL> with foo as (select rownum id, column1, column2, length(regexp_replace(column2, '[^~]', ''))-1 elem_cnt
2 from your_table)
3 select column1, elem
4 from (select column1, elem, f
5 from foo
6 model partition by(id)
7 dimension by(0 as f)
8 measures(column1, column2, elem_cnt,
9 cast('' as varchar2(4000)) elem)
10 rules (elem [for f from 0 to elem_cnt[0]-1 increment 1]
11 = substr(column2[0], instr(column2[0], '~', 1, cv(f)+1) + 1,
12 instr(column2[0], '~', 1, cv(f)+2) - instr(column2[0], '~', 1, cv(f)+1) - 1),
13 column1[any] = column1[0]))
14 order by f;
COLUMN1 ELEM
-------------------- --------------------
abcd 123
abcd abd
foo test
foo test2
foo2 test
または 11g の再帰サブクエリ ファクタリング:
SQL> with data (id, column1, column2, elem, elem_cnt, curr_elem)
2 as (select rownum id, column1, column2,
3 substr(column2, instr(column2, '~') + 1,
4 instr(column2, '~', 1, 2) - instr(column2, '~') - 1) elem,
5 length(regexp_replace(column2, '[^~]', ''))-1 elem_cnt,
6 1 as curr_elem
7 from your_table
8 union all
9 select rownum id, column1, column2,
10 substr(column2, instr(column2, '~', 1, elem_cnt) + 1,
11 instr(column2, '~', 1, elem_cnt+1) - instr(column2, '~', 1, elem_cnt) - 1) elem,
12 length(regexp_replace(column2, '[^~]', ''))-1 elem_cnt,
13 curr_elem + 1
14 from data
15 where curr_elem < elem_cnt)
16 select column1, elem
17 from data
18 order by column1, curr_elem;
COLUMN1 ELEM
-------------------- --------------------
abcd 123
abcd abd
foo test
foo test2
foo2 test