Преобразование базы 36 в базовую 10 с использованием только SQL
Возникла ситуация, когда мне нужно выполнить преобразование базы 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.
EDIT - это назад... при условии, что 01Z перевести его на 71.
В качестве взятки каждый полезный ответ получает бесплатное повышение.
Спасибо
Зла.
Ответы
Ответ 1
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)
)
)
Ответ 2
Для 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 вам нужно будет добавить больше значений в вектор положения.