Как перевернуть строку после токенизации в SQL - PullRequest
1 голос
/ 13 октября 2010

Мне нужно токенизировать строку и обратить ее в SQL.Например, если строка «L3: L2: L1: L0», мне нужно изменить ее на «L0: L1: L2: L3».Токенизация может быть выполнена с использованием разделителя ':', а затем обратным.Пожалуйста, предложите функцию в SQL для того же.

Заранее спасибо, Гита

Ответы [ 7 ]

4 голосов
/ 13 октября 2010

Если возможно, лучшим решением было бы изменить ваши данные таким образом, чтобы каждое значение сохранялось в отдельной строке.

Если это не сработает, вы можете создать функцию PL / SQL.

Если вам нужно решение исключительно на основе SQL, обычно вам нужно разделить каждое значение на несколько строк (перекрестное объединение с таблицей объектов или соединение по уровню <= максимальное количество элементов), а затем повторно объединитьданные, используя один из дюжины различных методов (listagg, collect, stragg, xml, sys_connect_by_path и т. д.) </p>

Еще один способ только для SQL - использовать регулярные выражения.Это, вероятно, самый быстрый, но он работает только с 9 элементами, потому что Oracle поддерживает только 9 обратных ссылок:

--Get everything except the extra ':' at the end.
select substr(string, 1, length(string) - 1) string from
(
  select regexp_replace(
    --Add a delimter to the end so all items are the same
    'L3:L2:L1:L0'||':'
    --Non-greedy search for anything up to a : (I bet there's a better way to do this)
    ,'(.*?:)?(.*?:)?(.*?:)?(.*?:)?(.*?:)?(.*?:)?(.*?:)?(.*?:)?(.*?:)?(.*?:)?'
    --Reverse the back-references
    ,'\9\8\7\6\5\4\3\2\1') string
  from dual
);
1 голос
/ 13 октября 2010
declare
  s varchar2(1000) := 'L 1 0:L9:L8:L7:L6:L5:L4:L3:L2:L1:L0';
  j number := length(s);
begin
  for i in reverse 1..length(s) loop
    if substr(s, i, 1) = ':' then
      dbms_output.put(substr(s, i + 1, j - i) || ':');
      j := i - 1;
    end if;
  end loop;    
  dbms_output.put_line(substr(s, 1, j));
end;
1 голос
/ 13 октября 2010

Вот решение, использующее конвейерную функцию PL / SQL для разделения элементов:

create type t_str_array as table of varchar2(4000);

create or replace function split_str (p_str in varchar2,
                                      p_separator in varchar2 := ':') return t_str_array pipelined
as
  l_str varchar2(32000) := p_str || p_separator;
  l_pos pls_integer;
begin

  loop
    l_pos := instr(l_str, p_separator);
    exit when (nvl(l_pos,0) = 0);
    pipe row (ltrim(rtrim(substr(l_str,1,l_pos-1))));
    l_str := substr(l_str, l_pos+1);
  end loop;

  return;

end split_str;

Тогда вы бы использовали обычный SQL для упорядочения элементов:

select * from table(split_str('L3:L2:L1:L0')) order by column_value
1 голос
/ 13 октября 2010

Что-то вроде:

SELECT
  REGEXP_REPLACE('L1:L2:L3',
                 '([[:alnum:]]{1,}):([[:alnum:]]{1,}):([[:alnum:]]{1,})',
                 '\3 \2 \1') "REGEXP_REPLACE"
from dual

Но вам может понадобиться подробно описать, что представляет собой токен.

0 голосов
/ 12 февраля 2017

Улучшение ответа Кевана, вот что я попробовал:

select listagg(TOKEN, ':') WITHIN GROUP (ORDER BY TOKEN_LEVEL DESC)
from
(SELECT  REGEXP_SUBSTR( myStr,'[^:]+', 1, LEVEL )  AS TOKEN, LEVEL TOKEN_LEVEL
FROM    dual
CONNECT BY REGEXP_SUBSTR( myStr, '[^:]+', 1, LEVEL ) IS NOT NULL);
0 голосов
/ 13 ноября 2013

Преобразовать элементы в строке CSV в записи, подавляя все значения NULL:

SELECT  REGEXP_SUBSTR( :csv,'[^,]+', 1, LEVEL )  AS element
FROM    dual
CONNECT BY REGEXP_SUBSTR( :csv, '[^,]+', 1, LEVEL ) IS NOT NULL ;

Преобразование элементов в строке CSV в записи с сохранением значений NULL (но не в порядке):

SELECT   REGEXP_SUBSTR( :csv,'[^,]+', 1, LEVEL )  AS element
FROM    dual
CONNECT BY LEVEL <= LENGTH( :csv ) - LENGTH( REPLACE( :CSV, ',' ) ) + 1 ;
0 голосов
/ 13 октября 2010

Поскольку вы используете Oracle, было бы легко сгенерировать хранимую процедуру Java с передачей строки, а затем

  1. разделить строку на массив
  2. цикл цикла назад и объединить полученную строку
  3. вернуть полученную строку

это будет небольшой код Java и не медленнее, чем pl / sql.но если вы хотите использовать pl / sql, вы также можете использовать DBMS_UTILITY.table_to_comma / .comma_to_table.Но в качестве имени функции предположим -> вы должны использовать "," в качестве токена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...