Как использовать разные разделители групп для тысяч и миллионов. оракул - PullRequest
0 голосов
/ 26 октября 2019

Мне нужно отобразить разные результаты в следующем формате, например:

40000000 до 40'000,000

Я пытался использовать это, но когда я пробую 2 разных группы разделителей, я получаю "недопустимая модель формата чисел "ошибка:

select to_char(9999999999, '9g999g99999g9', 'NLS_NUMERIC_CHARACTERS='',.''')
from dual;

Также попытался использовать substr и replace, но это не работает во всех случаях (например, когда результат 3000000 или 700000000). Это работает, но это не оптимальное решение.:

SELECT substr(replace('40,000,000',',',''''),0,length(40000000)-2)|| substr('40,000,000',-4) from dual; 

Как выглядит фактический выбор, если я использую предыдущий код.

SELECT substr(replace(to_char(oTOTAL_SENIOR, '999,999,999'),',',''''),0,length(oTOTAL_SENIOR)-2)|| substr(to_char(oTOTAL_SENIOR, '999,999,999'),-4) from dual

Предыдущий выбор становится ошибочным, когда я используюsubstr replace и to_char вместе из-за '999,999,999'.

Я также пытался использовать regexp_replace, но я не очень хорош в этом. Я знаю, что мне нужно заменить все, кроме последних 4 символов (, 000), но я не знаю, как.

Любая помощь будет оценена.

1 Ответ

0 голосов
/ 26 октября 2019

Вам понадобится кто-то умнее меня, чтобы сделать это правильно, но - пока, посмотрите, поможет ли это.

Я на XE 11g;чтобы избежать ошибки «больше нет данных для чтения из сокета», которую я получил на последних этапах этого запроса (я полагаю, это было связано с двумя обращениями строк), я создал свою собственную «обратную» функцию. Есть недокументированная функция reverse, но я не хочу ее использовать.

По сути, она переворачивает строку, которую вы передаете в качестве параметра. Для чего мне это нужно? Я обнаружил, что проще изменить значения, разделить их на 3 на 3 на 3 символа и применить те «странные» разделители, которые вы хотите. Кроме того, это делает весь код проще . Это может быть сделано без него, но - как я уже сказал - больше никаких данных для чтения из сокета не допустит. Извините за это.

Теперь кто-то скажет: почему вы (в смысле: я, LF) не сделали этого с использованием PL / SQL полностью и не поместили everything в функцию? Никаких особых причин и никаких проблем в этом, если необходимо.

ОК, вот оно:

SQL> create or replace function f_reverse (par_string in varchar2)
  2    return varchar2
  3  is
  4    retval varchar2(20);
  5  begin
  6    select listagg(substr(par_string, level, 1))
  7           within group (order by level desc)
  8      into retval
  9      from dual
 10      connect by level <= length(par_string);
 11
 12    return retval;
 13  end;
 14  /

Function created.

SQL> select f_reverse('1234') from dual;

F_REVERSE('1234')
---------------------------------------------------------------------
4321

SQL>

Наконец, вот что вы хотите:

SQL> with test (id, col) as
  2    (select 1, 40100200 from dual union all
  3     select 2,  2300400 from dual union all
  4     select 3,   700500 from dual union all
  5     select 4,    25700 from dual union all
  6     select 5,     6300 from dual union all
  7     select 6,      555 from dual
  8    )
  9  select id,
 10    regexp_replace(
 11                    f_reverse(
 12                      substr(f_reverse(col), 1, 3) ||','||
 13                      substr(f_reverse(col), 4, 3) || chr(39) ||
 14                      substr(f_reverse(col), 7)
 15                      ), '^[^0-9]+', '') result
 16  from test;

        ID RESULT
---------- ----------
         1 40'100,200
         2 2'300,400
         3 700,500
         4 25,700
         5 6,300
         6 555

6 rows selected.

SQL>

Что он делает?

  • строки # 1 - 7 - пример данных
  • строки # 9 и далее - полезный код
  • строки # 12 - 14 - разделение в обратном порядкевыборка данных в подстроки длиной 3 символа
    • строка # 12 - объединенная ,, так как это тысячи разделитель
    • строка # 13 - конкатенированная chr(13) которая ', миллионы разделитель
  • строка # 11 - обратная каскадная "перевернутая" строка назад
  • строка # 10 - удаление возможных нечисловыхсимволы от начала результата (это разделители для значений, которые короче «тысяч» или «миллионов»)
...