有没有一种简单的方法可以从两个整数复合键创建一个唯一的整数键?

问题描述 投票:5回答:9

由于各种原因,与问题关系不大,我有一个表,表的复合键是由两个整数组成的,我想从这两个数字中创建一个唯一的键。我最初的想法是把它们连在一起,但当我意识到(51,1)的复合键将导致与(5,11)相同的唯一键,即511时,我很快就遇到了问题。

有谁有一个巧妙的方法,可以从两个整数中生成一个整数,使生成的整数对起始整数是唯一的?

编辑 在面对大量的数学运算之后 我意识到我应该把一个细节包括在内 就是问题中的键的大小。在起源对中,第一个键目前是6位数,并且在系统的生命周期中可能会保持在7位数;第二个键还没有大于20。鉴于这些限制条件,看起来问题就不那么艰巨了。

tsql math primary-key uniqueidentifier composite-key
9个回答
2
投票

用一个足够高的值乘以一个

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)

22
投票

你可以用数学方法证明这是不可能的 如果你想让结果中的密钥 包含的比特数和它的两个组成部分相同的话. 然而,如果你从两个 32 位的 ints 开始,并且可以使用 64 位的 int 来计算结果,你显然可以这样做。

key1 << 32 | key2

SQL语法

SELECT key1 * POWER(2, 32) + key2

5
投票

这一点已经有相当详细的讨论了(不过,正如递归所说,输出必须由比单个输入更多的位组成)。

将两个整数以唯一的、确定的方式映射到1上。

如何使用两个数字作为地图键

http:/en.wikipedia.orgwikiCantor_pairing_function#Cantor_pairing_function。


2
投票

只有当你有一个键的上界时,你才能做到这一点。假设你有 key1key2up1 是一个数值,即 key1 将永远不会达到,那么你可以这样组合键。

combined = key2 * up1 + key1;

即使理论上密钥可以无限制地增长, 但在实践中通常可以估算出一个保存上限。


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

这种方法也适用于任何数量的钥匙.


1
投票

由于我喜欢你的问题的理论方面(它真的很美),并且与许多实际答案所说的相矛盾,我想对你的标签中的 "数学 "部分给出一个答案:)

事实上 将任何两个数字(或实际上任何数字系列)映射到一个数字。这就是所谓的 哥德尔数 并在1931年由库尔特-哥德尔首次发表。

举个简单的例子,与你的问题;比如说我们有两个变量v1和v2。那么v3=2v1*3v2 会给出一个唯一的编号。这个数字也是唯一的标识v1和v2。

当然,由此产生的数字v3可能会增长得不快。请把这个回答当作是对你问题中理论方面的回答。


1
投票

为mysql写了这些,他们工作得很好

创建函数 pair (x BIGINT unsigned, y BIGINT unsigned) 返回 BIGINT unsigned DETERMINISTICRETURN ((x + y) * (x + y + 1)) 2 + y;

创建函数 reversePairX (z BIGINT unsigned) 返回 BIGINT unsigned DETERMINISTICRETURN (FLOOR((-1 + SQRT(1 + 8 * z))2)) * ((FLOOR((-1 + SQRT(1 + 8 * z)))+ 3) 2 - z;

创建函数 reversePairY (z BIGINT unsigned) RETURNS BIGINT unsigned DETERMINISTICRETURN z - (FLOOR((-1 + SQRT(1 + 8 * z))2)) * ((FLOOR((-1 + SQRT(1 + 8 * z))2) + 1) 2;


0
投票

冒着听起来很有面子的风险。

NewKey = fn(OldKey1, OldKey2)

其中fn()是一个函数,它从添加到现有表中的一列中查找一个新的自编号键值。

很明显,两个整数字段比单个整数字段可以容纳成倍的数值。


0
投票

为什么不直接使用ROW_NUMBER()或IDENTITY(int,1,1)来设置新的ID呢?它们真的需要有关系吗?

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.