通过使用分隔符oracle进行分组

时间:2013-01-09 12:58:11

标签: oracle stringtokenizer

我的数据格式为

数据

column1 column2
abcd    ~123~abd~

第2列中的数据用〜

分隔

输出应采用两行格式

column1 column2
abcd    123
abcd    abd

可以请一些帮助。

2 个答案:

答案 0 :(得分:0)

Oracle没有内置的字符串标记生成器,但它很容易构建我们自己的。有几个不同的解决方案(在SO和更广泛的互联网上)但我将使用一个函数string_tokenizer(),我在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;

顺便说一下TRIM()调用是必要的,以删除~的前导和尾随实例(虽然也许tokenizer函数可以处理它。嗯...)

答案 1 :(得分:0)

样本数据为

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