Преобразование Base 36 в Base 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.

В качестве взятки каждый полезный ответ получает бесплатный голос.

Спасибо

Зло.


person EvilTeach    schedule 02.04.2010    source источник
comment
Мне просто любопытно (мне всегда хотелось найти повод использовать разные базы для хранения данных); для чего используется база 36 данных?   -  person David Murdoch    schedule 02.04.2010
comment
И мне любопытно, почему это нужно делать в SQL, это не очень распространено.   -  person Georg Schölly    schedule 02.04.2010
comment
Преимущество базы 36 заключается в том, что вы можете использовать встроенное устройство с ограниченной клавиатурой для ввода. Затем интерпретация его как base36 вместо строки более эффективна из-за размера, и, кроме того, вы можете рассчитывать с ним, используя функции по умолчанию.   -  person Henri    schedule 02.04.2010
comment
+1, один из самых интересных вопросов, который я видел в последнее время   -  person DCookie    schedule 03.04.2010
comment
@david Это уникальный идентификатор из устаревшей системы. Подумайте об этом как о закодированном порядковом номере. @georg Это политический вопрос. Выбери свои битвы и все такое. @dcookie, спасибо ....   -  person EvilTeach    schedule 03.04.2010


Ответы (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

or

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

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

person Matthew Erwin    schedule 15.01.2015

person    schedule
comment
+1, саииееет! Прекрасная иллюстрация использования синтаксиса подключения по уровням. - person DCookie; 03.04.2010
comment
да. Замените строку base36 оператором case. Спасибо, Дэйв. - person EvilTeach; 03.04.2010