3

クライアントが Excel で生成した関数を SQL でエミュレートしようとしています。実際には、エンタープライズ データベース システムの 1 つで、一意の 10 桁の数値 (VARCHAR) を主キーとして持っています。別のデータベース内では、一意の 5 桁の英数字の識別子が必要です。彼らは、その 5 桁の英数字の値が 10 桁の数字の表現であることを望んでいます。そこで、彼らが Excel で行ったことは、10 桁の数字をペアに分割し、それらの各ペアを 16 進数値に変換してから、それらをつなぎ合わせるというものでした。

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 文字列を取得し、できるだけ少ない文字数で英数字で表現します。結果の文字列も一意である必要があります。

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 億個の要素のセットを約 6,000 万個のセットにマッピングすることはできません。

ここで、クライアントのコードが何をしているかを詳しく見てみましょう。

そこで、彼らが Excel で行ったことは、10 桁の数字をペアに分割し、それらの各ペアを 16 進数値に変換してから、それらをつなぎ合わせるというものでした。

これは 100% 正確ではありません。Excel コードは最初の 2 桁を使用することはありませんが、残りの 8 桁に対してこの操作を実行します。このアルゴリズムには、直感的には明らかではない 2 つの主な問題があります。

  1. 2 つの 10 桁の数字を同じ 5 桁の数字にマッピングできます。数値 1000000117 と 1000001701 を考えてみましょう。1000000117 の最後の 4 桁は 1 11 にマップされ、1000001701 の最後の 4 桁は 11 1 にマップされます。これにより、両方が 00111 にマップされます。

  2. 5 桁の数字が 5 桁にならない場合もあります。たとえば、1000001616 は 001010 にマップされます。

それで、可能な解決策は何ですか?その 5 桁の数字が一意かどうか気にしない場合、MySQL では次のようなものを使用できます。

hex(<NUMERIC VALUE> % 0xFFFFF)
于 2011-07-26T23:17:00.767 に答える
1

10^10 底 2 の対数は 33.219280948874 です。

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

したがって、この数値を表すには 34 ビットが必要です。16 進数では、これには 34/4 = 8.5 文字が必要で、5 文字よりもはるかに多くなります。

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

Excel マクロは、10 文字の文字列の最初の 4 (または 6) 文字を無視しています。

16 の代わりにbase 36でエンコードを試すことができます。これにより、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

5 文字にするには、基数 100 が必要です

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

100 の印刷可能な ASCII 文字がないため、zkhr も説明したように、ASCII を超えることを望まない限り、これは機能しません。

于 2011-07-26T22:29:34.773 に答える
0

あなたの質問は興味深いものでした (私は答えを知っているとは言いませんが) 。 10 進数から 16 進数への with.html

于 2011-07-26T22:13:27.140 に答える