7

質問にあまり関係のないさまざまな理由で、2つの整数で構成された複合キーを含むテーブルがあり、これら2つの数値から単一の一意キーを作成したいと思います。私の最初の考えはそれらを連結することでしたが、(51,1)の複合キーが(5,11)と同じ一意のキー、つまり511になることに気付いたとき、すぐに問題に遭遇しました。

生成された整数が開始整数のペアに一意になるように、2つの整数から整数を生成する賢い方法はありますか?

編集:印象的な量の数学に直面した後、私が含めるべき詳細の1つは、問題のキーのサイズであることに気付きました。元のペアでは、最初のキーは現在6桁であり、システムの存続期間中はおそらく7桁のままになります。2番目のキーはまだ20を超えていません。これらの制約を考えると、問題はそれほど困難ではないように見えます。

4

9 に答える 9

22

結果のキーに2つのコンポーネントと同じビット数を含める場合は、これが不可能であることを数学的に証明できます。ただし、2つの32ビット整数から始めて、結果に64ビット整数を使用できる場合は、明らかに次のようなことを行うことができます。

key1 << 32 | key2

SQL構文

SELECT key1 * POWER(2, 32) + key2
于 2009-11-16T21:46:08.800 に答える
5

これについては、すでにかなり詳細に説明されています(ただし、再帰的に述べたように、出力は個々の入力よりも多くのビットで構成されている必要があります)。

一意で決定論的な方法で、2つの整数を1つにマッピングします

2つの数字を地図記号として使用する方法

http://en.wikipedia.org/wiki/Cantor_pairing_function#Cantor_pairing_function

于 2009-11-16T21:52:51.967 に答える
2

キーの1つに上限がある場合にのみ、これを実行できます。とがkey1ありkey2、決して到達しないup1値であるkey1とすると、次のようにキーを組み合わせることができます。

combined = key2 * up1 + key1;

キーが理論的に無制限に大きくなる可能性がある場合でも、実際には通常、保存の上限を見積もることができます。

于 2009-11-16T21:54:30.883 に答える
2

十分に高い値で1を乗算します

SELECT id1 * 1000000 + id2

または、テキスト連結を使用します。

SELECT CAST(CAST(id1 AS nvarchar(10)) + RIGHT('000000' + CAST(id2 AS nvarchar(10)), 6) AS int)

または、整数のものをスキップして、IDを数値以外のもので区切ります。

SELECT CAST(id1 AS nvarchar) + ':' + CAST(id2 AS nvarchar)
于 2009-11-16T21:57:52.557 に答える
2

私はあなたの質問の理論的な側面が好きで(それは本当に美しいです)、そして実際的な答えの多くが言うことと矛盾するので、私はあなたのタグの「数学」の部分に答えを与えたいです:)

実際、任意の2つの数値(または実際には任意の一連の数値)を1つの数値にマップすることができます。これはゲーデル数と呼ばれ、1931年にKurtGödelによって最初に公開されました。

簡単な例を挙げると、あなたの質問です。2つの変数v1とv2があるとします。その場合、v3 = 2 v1 * 3v2は一意の番号を与えます。この番号は、v1とv2も一意に識別します。

もちろん、結果の数v3は望ましくないほど急速に増加する可能性があります。この回答を、質問の理論的側面への回答として受け取ってください。

于 2009-11-19T16:51:59.277 に答える
1

提案されたソリューションは両方とも、受け入れられるキーの範囲に関するある程度の知識を必要とします。

この仮定を避けるために、数字を一緒に浅瀬にすることができます。

Key1 = ABC => Digits = A, B, C
Key2 = 123 => Digits = 1, 2, 3
Riffle(Key1, Key2) = A, 1, B, 2, C, 3

十分な桁がない場合は、ゼロパディングを使用できます。

Key1 = 12345, Key2 = 1 => 1020304051

この方法は、任意の数のキーに対しても一般化されます。

于 2009-11-16T22:03:12.423 に答える
1

これらをmysql用に作成しました。正常に動作します

CREATE FUNCTION pair(x BIGINT unsigned、y BIGINT unsigned)RETURNS BIGINT unsigned DETERMINISTIC RETURN((x + y)*(x + y + 1))/ 2 + y;

CREATE FUNCTION reversePairX(z BIGINT unsigned)RETURNS BIGINT unsigned DETERMINISTIC RETURN(FLOOR((-1 + SQRT(1 + 8 * z))/ 2))*((FLOOR((-1 + SQRT(1 + 8 * z)) / 2))+ 3)/ 2-z;

CREATE FUNCTION reversePairY(z BIGINT unsigned)RETURNS BIGINT unsigned DETERMINISTIC RETURN z-(FLOOR((-1 + SQRT(1 + 8 * z))/ 2))*((FLOOR((-1 + SQRT(1 + 8 * z ))/ 2))+ 1)/ 2;

于 2013-11-05T20:25:52.100 に答える
0

ファセットに聞こえるリスクがあります:

NewKey = fn(OldKey1, OldKey2)

ここで、fn()は、既存のテーブルに追加された列から新しい自動番号付きキー値を検索する関数です。

明らかに、2つの整数フィールドは、単一の整数フィールドよりも指数関数的に多くの値を保持できます。

于 2009-11-16T21:54:27.887 に答える
0

ROW_NUMBER()またはIDENTITY(int、1,1)を使用して新しいIDを設定してみませんか?彼らは本当に関係している必要がありますか?

于 2009-11-17T11:45:09.610 に答える