2009-11-16 33 views
4

由於各種原因與問題沒有太大關係,我得到了一個由兩個整數組成的組合鍵的表格,我想從這兩個數字中創建一個唯一的鍵。我最初的想法是將它們連接起來,但當我意識到(51,1)的組合鍵將導致與(5,11)相同的唯一鍵,即511時,我迅速遇到了問題。是否有一種簡單的方法來從兩個整數組合鍵創建唯一的整數鍵?

有沒有人有一種巧妙的方法來從兩個整數中生成一個整數,這樣生成的整數對於這對起始整數是唯一的?

編輯:在遇到大量的數學問題之後,我意識到我應該包含的一個細節是有問題的鍵的大小。在始發對中,第一個鍵目前是6位數字,並且在系統的整個生命週期中可能會保持7位數字;第二個關鍵還沒有超過20個。鑑於這些限制,看起來這個問題不那麼令人生畏。

+1

沒有DBA應該讓你擺脫這個 - 如果需要的話,創建一個primark密鑰列並在兩列上使用唯一約束 – 2009-11-16 21:53:40

+0

請參閱Matt Ball的重複答案 – 2009-11-16 22:00:32

回答

2

乘以一個足夠高的值

SELECT id1 * 1000000 + id2 

或者使用文本串聯:

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

或跳過整數事情和標識的東西非數字分開:

SELECT CAST(id1 AS nvarchar) + ':' + CAST(id2 AS nvarchar) 
20

如果您希望得到的密鑰包含與其兩個組件相同數量的位,您可以從數學上證明這是不可能的。但是,如果有兩個32位的整數開始,可以使用64位的int的結果,你可以明顯地做這樣的事情:

key1 << 32 | key2 
+0

這個。當然,確保你在這兩個整數中加入了理智檢查,以確保它們都是32位。 (假設你使用帶符號整數,它們需要小於2^31或2,147,483,648)。 – BlairHippo 2009-11-16 21:51:26

+0

不幸的是,我在T-SQL中這樣做並且缺少一個移位操作符。 – abeger 2009-11-16 21:59:02

+4

然後假裝乘法的母親。 :-)我認爲「key1 * 2^32」完成同樣的事情,但我的數學有點生疏。 – BlairHippo 2009-11-16 22:03:28

4

這在相當數量的細節已經討論過了(如遞歸表示,但是,輸出必須包含比單個輸入更多的位)。

Mapping two integers to one, in a unique and deterministic way

How to use two numbers as a Map key

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

+0

+1對於Cantor配對功能! – azheglov 2009-11-16 22:13:00

+0

相當複雜。這些答案讓我失去了「雙眼」。 :p – Kzqai 2009-11-16 22:15:02

+0

@Tchalvak:如果你不是一個數學的人,只需保持維基百科的條款你不知道! (就我個人而言,我真的很喜歡用那種高效的拖延來「教育」自己。)它歸結爲非常簡單的東西;使用花哨的數學詞彙只是使定義簡明扼要。 – 2009-11-16 22:48:20

0

在冠冕堂皇的風險開玩笑:

NewKey = fn(OldKey1, OldKey2) 

其中,fn()是從查找新autonumbered鍵值的功能列添加到您現有的表。

很明顯,兩個整數字段可以比一個整數字段指數多地保存值。

2

如果您有一個密鑰的上限,則只能這樣做。假設你有key1key2,並up1是一個值,key1將永遠無法達到,那麼你可以結合鍵是這樣的:

combined = key2 * up1 + key1; 

即使密鑰理論上成長無極限,它通常是可以估計在實踐中保存上限。

+0

我喜歡,比我的回答更乾淨。只需要確保您始終按照預定義的順序對這些鍵進行「編碼」,並按照相同的順序將它們「解碼」。 – Kzqai 2009-11-16 22:22:11

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

此方法還概括爲任何數量的鍵。

0

爲什麼不使用ROW_NUMBER()或IDENTITY(int,1,1)來設置新的ID?他們真的需要關係嗎?

1

因爲我喜歡你的問題的理論方面(它真的很漂亮),並且與許多實際答案中的內容相抵觸,所以我想回答一下你的標籤中的「數學」部分:)

事實上,有可能將任何兩個數字(或實際上任何系列的數字)映射到一個數字。這被稱爲Gödel number,並於1931年由KurtGödel首次發表。

舉個簡單的例子,用你的問題;假設我們有兩個變量v1和v2。然後v3 = 2 v1 * 3 v2會給出一個唯一的數字。該數字還唯一標識v1和v2。

當然,得到的數字v3可能會快速增長,不合需要。請把這個答案作爲對你問題理論方面的回答。

1

寫這些爲MySQL它們很好地工作

CREATE FUNCTION pair(X BIGINT無符號,Y BIGINT無符號) RETURNS BIGINT無符號DETERMINISTIC RETURN((X + Y)*(X + Y + 1))/ 2 + y;

CREATE FUNCTION reversePairX(Z BIGINT無符號) RETURNS BIGINT無符號DETERMINISTIC RETURN(FLOOR(( - 1 + SQRT(1個+ 8 * Z))/ 2))*((FLOOR(( - 1 + SQRT( 1 + 8 * z))/ 2))+ 3)/ 2-z;

CREATE FUNCTION reversePairY(Z BIGINT無符號) RETURNS BIGINT無符號DETERMINISTIC RETURNž - (FLOOR(( - 1 + SQRT(1 + 8 * Z))/ 2))*((FLOOR(( - 1 + SQRT(1 + 8 * z))/ 2))+ 1)/ 2;

相關問題