2014-12-09 2 views
0

Я пытаюсь это заявлениерасщепление колонки во многих строках дает слишком много строк

with value_table as 
(select 1 id, '1/2/3' objnr from dual 
union all 
select 2, '4/5/6' from dual), 
test as 
(select id, objnr col from value_table where id in (1, 2)) 
    select id, regexp_substr(col, '[^/]+', 1, level) result 
    from test 
    connect by level <= length(regexp_replace(col, '[^/]+')) + 1 
    order by 1 

Я хочу, чтобы получить 6 строк

1 1 
1 2 
1 3 
2 4 
2 5 
2 6 

, но я получаю Ряды несколько раз. Когда я пытаюсь использовать только один идентификатор, он работает без проблем. Как обходной путь, я просто сделал цикл для каждого отдельного идентификатора, другое решение - использовать разные, но для выполнения, когда я пытаюсь это сделать, требуется возраст, с реальными данными (более 1000 записей). Может ли кто-нибудь предоставить более сложное решение?

ответ

1

попробовать отличный, используемый ниже

with value_table as 
(select 1 id, '1/2/3' objnr from dual 
union all 
select 2, '4/5/6' from dual), 
test as 
(select id, objnr col from value_table where id in (1, 2)) 
    select distinct id, regexp_substr(col, '[^/]+', 1, level) result 
    from test 
    connect by level <= regexp_count(col, '[^/]+') 
order by 1 

опробованы sqlfiddle http://sqlfiddle.com/#!4/03d80/14

EDIT:

Если вы не хотите попробовать отчетливый ниже

with value_table as 
(select 1 id, '1/2/3' objnr from dual 
union all 
select 2, '4/5/6' from dual), 
test as 
(select id, objnr col from value_table where id in (1, 2)) 
    select id, regexp_substr(col, '[^/]+', 1, level) result 
    from test 
    connect by level <= regexp_count(col, '[^/]+') 
and id = prior id 
    and prior dbms_random.value is not null 
order by 1 

который использует режим л пункт PRIOR sqlfiddle ссылка http://sqlfiddle.com/#!4/03d80/31

+0

Как указано в вопросе. Разница не является ценным решением, когда я использую реальные данные. –

1

Этот запрос выполняется

with test as 
(
select 1 id, '1/2/3' objnr from dual union all 
select 2 id, '4/5/6' objnr from dual 
) 
select id, regexp_substr (objnr, '[^/]+', 1, rn) result 
from test 
cross 
join (select rownum rn 
     from (select max (length (regexp_replace (objnr, '[^/]+'))) + 1 mx 
       from test 
      ) 
    connect by level <= mx 
    ) 
where regexp_substr (objnr, '[^/]+', 1, rn) is not null 
and id in (1, 2) 
order by id,result ; 

ID РЕЗУЛЬТАТ


Если вы используете Oracle 11g, вы можете также использовать REGEXP_COUNT вместо комбинации regexp_replace и длины, которые будут выглядеть следующим образом:

cross 
join (select rownum rn 
    from (select max (regexp_count (objnr, '/') + 1) mx 
      from test 
     ) 
connect by level <= mx 
) 

иметь внешнее соединение поведение поэтому было сделано небольшое изменение, как показано ниже:

with test as 
    (
    select 1 id, '1/2/3' objnr from dual union all 
    select 2 id, '4/5/6' objnr from dual 
) 
    select id, regexp_substr (objnr, '[^/]+', 1, rn) result 
    from test 
    left outer join (select rownum rn 
      from (select max (regexp_count (objnr, '/') + 1) mx 
        from test 
       ) 
     connect by level <= mx 
     ) splits 
    ON splits.rn <= length(regexp_replace (objnr, '[^/]+'))+1  
    and id in (1, 2) 
    order by id,result ; 
+0

это работает, но мне все еще интересно, есть ли лучшее решение. –

Смежные вопросы