0

I have the data in the format

data

column1 column2
abcd    ~123~abd~

The data in column 2 is separated by ~

the output should be in the format in two rows

column1 column2
abcd    123
abcd    abd

can some please help.

APC
  • 144,005
  • 19
  • 170
  • 281
Umesh
  • 3
  • 2

2 Answers2

0

Oracle does not have a built-in string tokenizer but it's easy enough to build our own. There are several different solutions (both on SO and the wider interwebs) but I'll use a function, string_tokenizer() , I posted some while back in this other answer.

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;

By the way the TRIM() call is necessary to remove the leading and trailing instances of ~ (although perhaps the tokenizer function could handle that instead. Hmmm...)

Community
  • 1
  • 1
APC
  • 144,005
  • 19
  • 170
  • 281
0

with sample data as

SQL> select * from your_table;

COLUMN1              COLUMN2
-------------------- --------------------
abcd                 ~123~abd~
foo                  ~test~test2~
foo2                 ~test~

Model clause (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

or 11g recursive subquery factoring:

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
DazzaL
  • 21,638
  • 3
  • 49
  • 57
  • Hi Dazzal / APC, Thanks a lot for your answers. Its really pleasure to get these answers so quickly. I have used the queries amended as required and it really worked as per the requirement even though I am still trying to understand the entire logic. – Umesh Jan 17 '13 at 15:10