【问题标题】:Group by using a delimitor oracle使用分隔符 oracle 进行分组
【发布时间】:2013-01-09 12:58:11
【问题描述】:

我有格式的数据

数据

column1 column2
abcd    ~123~abd~

第2列的数据用~分隔

输出应该是两行格式

column1 column2
abcd    123
abcd    abd

请帮忙。

【问题讨论】:

    标签: oracle stringtokenizer


    【解决方案1】:

    以样本数据为

    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
    

    【讨论】:

    • 您好 Dazzal / APC,非常感谢您的回答。能这么快得到这些答案真的很高兴。我已经根据要求使用了修改后的查询,即使我仍在尝试理解整个逻辑,它也确实按照要求工作。
    【解决方案2】:

    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() 调用对于删除 ~ 的前导和尾随实例是必要的(尽管也许标记器函数可以处理它。嗯...)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2011-12-26
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 2020-09-16
      相关资源
      最近更新 更多