代码之家  ›  专栏  ›  技术社区  ›  EvilTeach

仅使用SQL将基36转换为基10

  •  13
  • EvilTeach  · 技术社区  · 14 年前

    出现了一种情况,我需要在sql语句的上下文中执行基36到基10的转换。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。 编辑-这是向后的…给定01Z,将其转换为71。

    作为贿赂,每一个有用的答案都会得到一个免费的投票。

    谢谢

    邪恶的。

    2 回复  |  直到 9 年前
        1
  •  23
  •   EvilTeach    14 年前
    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
  •  3
  •   Matthew Erwin    9 年前

    对于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的字符串,需要向位置向量添加更多的值。