Группировать с использованием оракула-ограничителя

У меня есть данные в формате

данные

column1 column2
abcd    ~123~abd~

Данные в столбце 2 разделяются символом ~

вывод должен быть в формате в два ряда

column1 column2
abcd    123
abcd    abd

возможно некоторые пожалуйста, помогите.

0
nl ja de

2 ответы

с данными выборки как

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

или 11 г рекурсивного подзапроса факторинга:

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
0
добавлено
Привет Dazzal/APC, Большое спасибо за ваши ответы. Его очень приятно получить эти ответы так быстро. Я использовал исправления по мере необходимости, и это действительно работало согласно требованию, хотя я все еще пытаюсь понять всю логику.
добавлено автор Umesh, источник

У 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() необходим, чтобы удалить ведущие и завершающие экземпляры ~ (хотя, возможно, функция токенизатора могла бы обрабатывать это. Hmmm ...)

0
добавлено
Oracle RU
Oracle RU
303 участник(ов)

Русскоязычная группа по Oracle. — Архитектура СУБД — PL/SQL — Оптимизация — Администрирование — Вакансии Oracle (указать инфу по вилке ЗП и удалёнке) Приглашайте коллег :-) Запрещены: личные оскорбления, обсуждения оффтопик вопросов политики и религии