3

我正在尝试在 SQL 中模拟客户端在 Excel 中生成的函数。实际上,它们有一个唯一的 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((值(MID(A2,9,2)))))

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

添加于 2011 年 8 月 2 日

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

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

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

4

3 回答 3

2

这个问题本质上是不可能的。您有一个 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)
于 2011-07-26T23:17:00.767 回答
1

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。

于 2011-07-26T22:29:34.773 回答
0

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

于 2011-07-26T22:13:27.140 回答