2013-11-13 1 views
0

Я использую OracleOracle: преобразование дефис разделенных числовые значения, разделенные запятыми диапазоне

У меня есть таблица с именем столбца ПОСЛЕДОВАТЕЛЬНОСТИ , который содержит значение в следующем формате: х, у, г, аб

Пример :

1) 1,2,3,6-8,9-11

2) 1,2,3,5,11

т.д.

1-й пример - проблема, которая у меня есть.

Я пишу запрос на выборку, как: SELECT * из таблицы, где Value IN (1,2,3,6-8,9-11)

Для этого, я хочу, чтобы преобразовать значения дефис (6 -8,9-22) в этом формате 6,7,8,9,10,11 После этого мой запрос будет

ВЫБЕРИТЕ * из таблицы, где Значение IN (1,2,3,6,7 , 8,9,10,11) Что будет решить мою проблему

Мой вопрос Как достичь этого преобразования значения типа (6-8,9-11) К (6,7,8,9,10,11-) в ORACLE

+0

Я ожидаю, что решение Флорин на боян будет иметь наиболее помогите вам. – Ben

+0

Да, нашел это полезным. благодаря – user2235603

ответ

0

еще один выбор

with str as 
(select '1,2,3,7-11' as ids from dual), 
i as 
(select replace(trim(substr(t1.str, 
          t1.curr_pos + 1, 
          decode(t1.next_pos, 0, length(t1.str) + 2, t1.next_pos) - t1.curr_pos - 1)), 
       ' ', 
       '') as item 
    from (select ids str, 
       decode(level, 1, 0, instr(ids, ',', 1, level - 1)) as curr_pos, 
       instr(ids, ',', 1, level) as next_pos 
      from str 
      connect by level <= length(ids) - length(replace(ids, ',', '')) + 1) t1), 
ii as 
(select case 
      when instr(item, '-') = 0 then 
       item 
      else 
       substr(item, 1, instr(item, '-') - 1) 
     end as first_item, 
     case 
      when instr(item, '-') = 0 then 
       item 
      else 
       substr(item, instr(item, '-') + 1) 
     end as last_item 
    from i), 
tmp_str as 
(select rownum as id, 
     (select listagg(ii.first_item + level - 1, ',') within group(order by level) 
      from dual 
      connect by level <= ii.last_item - ii.first_item + 1) as ids 
    from ii), 
tmp_str2 as 
(select t.*, length(ids) - length(replace(ids, ',', '')) + 1 as cnt from tmp_str t), 
tmp_dual as 
(select level as lv from dual connect by level <= (select max(cnt) as total_cnt from tmp_str2)), 
tmp_str3 as 
(select * 
    from (select id, lv, ids, cnt, row_number() over(partition by id order by lv) as rn from tmp_dual, tmp_str2) t1 
    where rn <= cnt) 
select distinct to_number(trim(substr(t1.str, 
             t1.curr_pos + 1, 
             decode(t1.next_pos, 0, length(t1.str) + 2, t1.next_pos) - t1.curr_pos - 1))) as id 
    from (select ids str, decode(lv, 1, 0, instr(ids, ',', 1, lv - 1)) as curr_pos, instr(ids, ',', 1, lv) as next_pos 
      from tmp_str3) t1 
order by 1 

результат

1 
2 
3 
7 
8 
9 
10 
11