Преобразовать строку с диапазонами числовых значений в строку отдельных чисел с запятой как разделителем
Допустим, есть символьная строка: 1-3,4,9,11-15.
Есть ли простой путь преобразовать её в строку отдельных чисел с запятой как разделителем в PL/SQL?
Можно найти множество решений, разбить строку по разделителю на отдельные значения, а также, собрать строку из отдельных значений. А как быть, если в строке встречаются диапазоны значений?
То есть, конечный результат хотелось бы видеть так: 1,2,3,4,9,11,12,13,14,15.
Свободный перевод вопроса Convert string with groups of numbers to a comma separated string with single numbers in PL/SQL от участника @Weltraumfahrer
Ответы (1 шт):
Взял за основу это решение (на db<>fiddle). Унаследовал с новым конструктором и одной вспомогательной функцией:
create or replace type TokenizerExt under Tokenizer (
constructor function TokenizerExt (
str varchar2, delimiter char:=',', spansign char:='-') return self as result,
static function range (str varchar2, spansign char) return tokenList)
/
create or replace type body TokenizerExt as
constructor function TokenizerExt (
str varchar2, delimiter char:=',', spansign char:='-') return self as result is
tmp tokenList := Tokenizer.split (str, delimiter);
begin
self.tokens := tokenList (); --:= Tokenizer (str, delimiter).tokens;
for i in 1..tmp.count loop
self.tokens := self.tokens multiset union TokenizerExt.range (tmp(i), spansign);
end loop;
return;
end;
static function range (str varchar2, spansign char) return tokenList is
ret tokenList := tokenList ();
p int;
begin
if regexp_like (str, '^\d+'||spansign||'\d+$') then
p := instr (str, spansign);
for d in (substr (str, 1, p-1))..(substr (str, p+1)) loop
ret.extend; ret(ret.last) := d;
end loop;
else
ret := tokenList (str);
end if;
return ret;
end;
end;
/
Даст ожидаемый результат:
select TokenizerExt ('1-3,4,9,11-15').join() result from dual
/
RESULT
------------------------------------------------------------
1,2,3,4,9,11,12,13,14,15