7
votes

Y a-t-il un moyen simple de créer une clé entière unique à partir d'une clé composite à deux entiers?

Pour diverses raisons qui ne sont pas trop utiles à la question, j'ai une table avec une clé composite composée de deux entiers et je souhaite créer une clé unique unique de ces deux chiffres. Ma pensée initiale était de les concaténer, mais j'ai rencontré rapidement un problème lorsque je me suis rendu compte qu'une clé composite de (51,1) entraînerait la même clé unique que (5,11), à savoir 511.

Est-ce que quelqu'un a un moyen intelligent de générer un entier sur deux entiers de sorte que l'entier généré soit unique à la paire d'entiers de départ?

edit: Après avoir été confronté à une quantité impressionnante de mathématiques, je me rends compte qu'un détail que j'aurais dû inclus est la taille des clés en question. Dans la paire d'origine, la première clé est de 6 chiffres et restera probablement dans 7 chiffres pour la vie du système; La deuxième clé n'a pas encore atteint de plus de 20 ans. Compte tenu de ces contraintes, on dirait que le problème est beaucoup moins décourageant.


2 commentaires

Aucun DBA ne devrait vous laisser sortir avec ceci - si besoin d'être, créer une colonne de clé primark et utiliser une contrainte unique sur les deux colonnes.


Voir la réponse de Matt Ball pour des doublons


9 Réponses :


22
votes

Vous pouvez prouver mathématiquement cela est impossible si vous souhaitez que la clé résultante comprend le même nombre de bits que ses deux composants. Toutefois, si vous commencez avec deux INT 32 bits et pouvez utiliser un Int 64 bits pour le résultat, vous pouvez évidemment faire quelque chose comme ceci: xxx pré>

Syntaxe SQL P>

SELECT key1 * POWER(2, 32) + key2


5 commentaires

Cette. Bien sûr, assurez-vous d'inclure des chèques de santé mentale sur les deux entiers pour vous assurer qu'ils sont tous deux 32 bits. (En supposant que vous utilisiez des entiers signés, ils devront être inférieurs à 2 ^ 31, à 2 147 483 648).


Malheureusement, je le fais dans T-SQL et je manque un opérateur bossu.


Puis simulez cette mère avec une multiplication. :-) Je pense que "Key1 * 2 ^ 32" accomplit la même chose, mais mes mathématiques sont un TAD Rusty.


De dbaspot.com/forums/sqlserver-programming / ... , pour atteindre @i << @j : Sélectionnez @I * Power (2, @j)


+1 Même si si key1 est un entier 32 bits, alors key1 << 32 == 0 (vous devez la jeter à 64 bits d'abord)



5
votes

Ceci a été discuté dans une juste quantité de détails déjà (comme ledite récursif, toutefois, la sortie doit être comprise en plus de bits que les entrées individuelles).

cartographier deux entiers à un, dans une manière unique et déterministe

Comment utiliser deux numéros comme clé de carte

http://fr.wikipedia.org/wiki/cantor_pairing_funcuncunction_pairing_function


2 commentaires

Assez compliqué. Ces réponses me sont perdues à "Bijectif". : p


@TCHALVAK: Si vous n'êtes pas une grande partie d'une personne mathématique, gardez simplement Wikipedia-ing les termes que vous ne connaissez pas! (Personnellement, j'aime vraiment "éduquer" moi-même avec ce genre de procrastination productive.) Cela se résume à des trucs assez simples; L'utilisation des mots mathématiques de fantaisie conserve simplement les définitions concises et exactes.



0
votes

au risque de retenue facétieuse: xxx

où Fn () est une fonction qui lève une nouvelle valeur de clé auto-au-dessus d'une colonne ajoutée à votre table existante. < P> Évidemment, deux champs entiers peuvent contenir de manière exponentielle plus de valeurs qu'un seul champ entier.


0 commentaires

2
votes

Vous ne pouvez le faire que si vous avez une limite supérieure pour l'une des clés. Dis que vous avez key1 et key2 et up1 est une valeur que key1 n'atteindra jamais, alors vous pouvez combiner Les clés comme ceci: xxx

même si les clés pouvaient se développer théoriquement sans limite, il est généralement possible d'estimer une limite supérieure de sauvegarde dans la pratique.


1 commentaires

J'aime, plus propre que ma réponse était. Il suffit de vous assurer que vous avez toujours "encoder" les clés dans les commandes prédéfinies et "décodez" dans le même ordre.



2
votes

multiplier un avec une valeur suffisamment élevée xxx

ou utilisez la concaténation du texte: xxx

ou ignorer la chose entier et séparer les identifiants avec quelque chose de non numérique: xxx


0 commentaires

1
votes

Les deux des solutions suggérées nécessitent des connaissances sur la gamme de clés acceptées.

Pour éviter de faire cette hypothèse, on peut riffler les chiffres ensemble.

clé1 = abc => chiffres = a, b, c
Key2 = 123 => chiffres = 1, 2, 3
Riffle (Key1, Key2) = A, 1, B, 2, C, 3

Le rembourrage zéro peut être utilisé quand il n'y a pas assez de chiffres:

clé1 = 12345, clé2 = 1 => 1020304051

Cette méthode est également généralisée pour un nombre quelconque de clés.


0 commentaires

0
votes

Pourquoi n'utilisez-vous pas simplement Row_Number () ou identité (int, 1,1) pour définir un nouvel identifiant? Ont-ils vraiment besoin d'être en relation?


0 commentaires

2
votes

Comme j'aime le côté théorique de votre question (c'est vraiment beau) et à contredire à quoi disent de nombreuses réponses pratiques, je voudrais donner une réponse à la partie "Math" de vos tags :)

En fait il est possible de cartographier deux chiffres (ou en réalité une série de chiffres) à un seul numéro. C'est ce qu'on appelle le numéro Gödel et a été publié pour la première fois en 1931 par Kurt Gödel.

Pour donner un exemple rapide, avec votre question; Disons que nous avons deux variables v1 et v2. Alors v3 = 2 v1 * 3 v2 donnerait un numéro unique. Ce numéro identifie également de manière unique V1 et V2.

Bien sûr, le nombre résultant v3 résultant peut augmenter de manière indésirable rapide. S'il vous plaît, prenez simplement cette réponse comme une réponse à l'aspect théorique de votre question.


0 commentaires

1
votes

a écrit celles-ci pour mysql ils fonctionnent bien

Créer une fonction paire (x bigint non signé, y Bigint non signé) Renvoie Bigint TRANSITIONNÉ DÉTERNINISTE Retour (x + y) * (x + y + 1)) / 2 + y;

Créer une fonction ReversePairx (Z Bigint Unsigné) Renvoie Bigint TRANSITIONNÉ DÉTERNINISTE Retour (plancher ((- 1 + sqrt (1 + 8 * Z)) / 2)) * ((((- 1 + sqrt (1 + 8 * z)) / 2)) + 3) / 2 - z ;

Créer une fonction ReversePairy (Z Bigint non signé) Renvoie Bigint TRANSITIONNÉ DÉTERNINISTE Retour Z - (étage ((- 1 + sqrt (1 + 8 * z)) / 2)) * ((((- 1 + sqrt (1 + 8 * z)) / 2)) + 1) / 2 ;


0 commentaires