【问题标题】:SQL - Create Unique AlphaNumeric based on a 10-digit integer stored as VARCHARSQL - 根据存储为 VARCHAR 的 10 位整数创建唯一 AlphaNumeric
【发布时间】:2011-07-26 22:02:51
【问题描述】:

我正在尝试模拟客户端在 Excel 中生成的 SQL 函数。实际上,它们有一个唯一的 10 位数值 (VARCHAR) 作为其企业数据库系统之一的主键。在另一个数据库中,它们需要一个唯一的 5 位字母数字标识符。他们希望 5 位字母数字值代表 10 位数字。所以他们在 excel 中所做的就是将 10 位数字分成对,然后将这些对中的每一对转换为十六进制值,然后将它们缝合在一起。

EXCEL公式为:

=IF(VALUE(MID(A2,1,4))>0,DEC2HEX(VALUE(MID(A2,3,2)))&DEC2HEX(VALUE(MID(A2,5,2)))&DEC2HEX( VALUE(MID(A2,7,2)))&DEC2HEX(VALUE(MID(A2,9,2))),DEC2HEX(VALUE(MID(A2,5,2)))&DEC2HEX(VALUE(MID(A2,7) ,2)))&DEC2HEX((VALUE(MID(A2,9,2)))))

我需要与此等效的 SQL。当然,如果有人知道一种更好的方法来实现基于 10 位数字的“5 位字母数字标识符”的目标,我会全力以赴。

2011 年 8 月 2 日添加

首先,感谢大家的回复。很高兴看到人们愿意帮助甚至享受它!根据所有的回复,我倾向于告诉我的客户他们的意图是合理的,只是他们的方法不合时宜。我也想推荐一个解决方案。所以挑战依然存在,只是稍作修改:

挑战:在 SQL 中,取一个 10 位唯一的 NUMERIC 字符串,并用尽可能少的字符以 ALPHANUMERICAL 方式表示它。结果字符串也必须是唯一的。

请注意,10 位字符串中的前 3-4 个字符可能是零,并且可以将它们剥离以缩短生成的字母数字字符串。不是必需的,但也许有帮助。

【问题讨论】:

    标签: sql hex varchar alphanumeric


    【解决方案1】:

    这个问题本质上是不可能的。您有一个 10 位数字值,您想将其转换为 5 位字母数字值。由于有 10 个数字字符,这意味着您的 10 位数字有 10^10 = 10 000 000 000 个唯一值。由于有 36 个字母数字字符(26 个字母 + 10 个数字),因此您的 5 位数字有 36^5 = 60 466 176 个唯一值。您不能将 100 亿个元素的集合映射到大约 6000 万个元素的集合中。

    现在,让我们仔细看看您的客户的代码在做什么:

    所以他们在 excel 中所做的就是将 10 位数字分成对,然后将这些对中的每一对转换为十六进制值,然后将它们缝合在一起。

    这不是 100% 准确的。 excel 代码从不使用前 2 位,而是对剩下的 8 位执行此操作。此算法有两个主要问题,可能不直观:

    1. 两个 10 位数字可以映射到同一个 5 位数字。考虑数字 1000000117 和 1000001701。1000000117 的后四位映射到 1 11,其中 1000001701 的后四位映射到 11 1。这导致两者都映射到 00111。

    2. 5 位数字甚至可能不是 5 位数字!例如,1000001616 被映射到 001010。

    那么,什么是可能的解决方案?好吧,如果你不关心那个 5 位数字是否唯一,在 MySQL 中你可以使用类似的东西:

    hex(<NUMERIC VALUE> % 0xFFFFF)
    

    【讨论】:

      【解决方案2】:

      10^10 base 2的对数是33.219280948874

      > return  math.log(10 ^ 10) / math.log(2)
      33.219280948874
      > = 2 ^ 33.21928
      9999993422.9114
      

      所以,它需要 34 位来表示这个数字。在十六进制中,这将需要 34/4 = 8.5 个字符,远远超过 5 个。

      > return  math.log(10 ^ 10) / math.log(16)
      8.3048202372184
      

      Excel 宏忽略了 10 个字符串的前 4 个(或 6 个)字符。

      您可以尝试使用 base 36 编码而不是 16。这将使您的字符数不超过 7 个。

      > return  math.log(10 ^ 10) / math.log(36)
      6.4254860446923
      

      流行的base 64 编码可以让您达到 6 个字符

      > return  math.log(10 ^ 10) / math.log(64)
      5.5365468248123
      

      即使Ascii85 编码也不会让你降到 5。

      > return  math.log(10 ^ 10) / math.log(85)
      5.1829075929158
      

      您需要以 100 为基数才能达到 5 个字符

      > return  math.log(10 ^ 10) / math.log(100)
      5
      

      没有 100 个可打印的 ASCII 字符,所以这不起作用,正如 zkhr 解释的那样,除非你愿意超越 ASCII。

      【讨论】:

        【解决方案3】:

        我发现您的问题很有趣(尽管我不声称知道答案)-出于兴趣,我在 Google 上搜索了一下,发现这可能对您有帮助 http://dpatrickcaldwell.blogspot.com/2009/05/converting-decimal-to-hexadecimal-with.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-23
          • 1970-01-01
          • 1970-01-01
          • 2021-11-19
          • 1970-01-01
          相关资源
          最近更新 更多