Преобразование базы 36 в базу 10 с использованием только SQL - PullRequest
13 голосов
/ 02 апреля 2010

Возникла ситуация, когда мне нужно выполнить преобразование из базы 36 в базу 10 в контексте оператора SQL.Похоже, в Oracle 9 или Oracle 10 ничего не встроено для решения подобных задач.Мой Google-Fu и AskTom предлагают создать функцию pl / sql для решения этой задачи.Это не вариант для меня на данный момент. Я ищу предложения о подходе, который мог бы помочь мне решить эту проблему.

Чтобы представить это в визуальной форме ...

WITH
Base36Values AS
(
    SELECT '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' myBase36 FROM DUAL
),
TestValues AS
(
    SELECT '01Z' BASE36_VALUE,
            71   BASE10_VALUE FROM DUAL
)
SELECT *
FROM Base36Values,
     TestValues

Я ищу что-то, чтобы вычислить значение 71, основываясь на вводе 01Z. РЕДАКТ.получает бесплатное голосование.

Спасибо

Зло.

Ответы [ 2 ]

23 голосов
/ 02 апреля 2010
select sum(position_value) from
(
  select power(36,position-1) * case when digit between '0' and '9' 
                                     then to_number(digit)
                                     else 10 + ascii(digit) - ascii('A')
                                end
          as position_value
    from (
          select substr(input_string,length(input_string)+1-level,1) digit, 
                 level position
            from (select '01Z' input_string from dual)
            connect by level <= length(input_string)
         )
)
3 голосов
/ 15 января 2015

Для T-SQL следующая логика будет выполнять задачу, которую выполняет код Oracle выше. Это общее общее решение, и оно будет поддерживать от Base-X до Base-10:

select
    sum(power(base,pos-1) *
            case when substring(cnv,pos,1) between '0' and '9' then 
                cast(substring(cnv,pos,1) as int) 
            else 10 + ascii(upper(substring(cnv,pos,1))) - ascii('A') end)
    from (values(reverse('01Z'), 36)) as t(cnv,base)
        left join (values(1),(2),(3),(4),(5),(6)) as x(pos)
            on pos <= len(cnv)

Для использования с другими базами просто используйте:

from (select cnv = reverse('FF'), base=16) as t

или

from (select cnv = reverse('101'), base=2) as t

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

...