Un bon algorithme pour générer un numéro de commande

autant j'aime utiliser des GUIDs que les identificateurs uniques dans mon système, il n'est pas très convivial pour les champs comme un numéro de commande où un client peut avoir à répéter cela à un représentant du service à la clientèle.

Qu'est-ce qu'un bon algorithme à utiliser pour générer un numéro d'ordre pour qu'il soit:

  • Unique
  • Non séquentielle (purement pour l'optique)
  • valeurs numériques seulement (de sorte qu'il peut être facilement lu à un CSR par téléphone ou à clavier en)
  • < 10 chiffres
  • peut être généré dans le niveau intermédiaire sans faire un aller-retour vers la base de données.

mise à jour (12/05/2009) Après avoir examiné attentivement chacune des réponses postées, nous avons décidé de randomiser un nombre de 9 chiffres dans le niveau intermédiaire pour être enregistré dans le DB. En cas de collision, nous régénérerons un nouveau numéro.

8
demandé sur Jason 2009-12-01 06:46:48

10 réponses

si le niveau intermédiaire ne peut pas vérifier quels "numéros d'ordre" existent déjà dans la base de données, le mieux qu'il peut faire sera l'équivalent de générer un nombre aléatoire. Cependant, si vous générez un nombre aléatoire qui est limité à moins de 1 milliard, vous devriez commencer à vous inquiéter des collisions accidentelles à environ sqrt(1 billion), i.e., après quelques dizaines de milliers d'entrées générées de cette façon, le risque de collisions est important. Que faire si le numéro de la commande séquentielle, mais d'une manière déguisée, c'est à dire le prochain multiple d'un grand nombre premier modulo 1 milliard -- est-ce que cela répondrait à vos besoins?

8
répondu Alex Martelli 2009-12-01 03:53:38

OK ressemble à un cas classique d'optimisation prématurée. Vous imaginez un problème de performance (Oh mon Dieu je dois accéder à la - horreur - base de données pour obtenir un numéro de commande! Mon qui pourrait être lent) et finir avec un gâchis alambiqué de générateurs aléatoires psuedo et une tonne de code de manipulation dupliqué.

une réponse pratique simple est d'exécuter une séquence par client. Le numéro de commande réel étant un composé du numéro du client et du numéro de commande. Vous pouvez facilement récupérer les dernière séquence utilisée lors de la récupération d'autres choses sur votre client.

5
répondu James Anderson 2009-12-01 06:00:50

Une option simple est d'utiliser la date et l'heure, par exemple. 0912012359, et si deux ordres sont reçus dans la même minute, incrémentez simplement le second ordre d'une minute (peu importe si le temps est écoulé, ce n'est qu'un numéro d'ordre).

Si vous ne voulez pas que la date soit visible, puis calculer le nombre de minutes depuis un point fixe dans le temps, par exemple. quand vous avez commencé à recevoir des ordres ou un autre rendez-vous Officiel. Encore une fois, avec le double contrôle/incrément.

Votre les concurrents n'en tireront rien, et c'est facile à mettre en œuvre.

2
répondu Will 2009-12-01 06:20:24

peut - être pourriez-vous essayer de générer un texte unique en utilisant une chaîne markov-voir ici pour un exemple d'implémentation en Python. Peut-être utiliser des nombres séquentiels (plutôt que des nombres aléatoires) pour générer la chaîne, de sorte que (espérons) le numéro de chaque ordre est unique.

Juste un avertissement, voir ici pour ce qui peut arriver si vous n'êtes pas prudent avec vos paramètres.

1
répondu a_m0d 2009-12-01 03:53:40

Une solution serait de prendre le hash d'un domaine de l'ordre. Cela ne garantit pas qu'il est unique par rapport aux numéros d'ordre de tous les autres ordres, mais la probabilité d'une collision est très faible. J'imagine que sans "faire un aller-retour à la base", il serait difficile de assurez-vous que le numéro de commande est unique.

dans le cas où vous n'êtes pas familier avec les fonctions de hachage, la page wikipedia est assez bonne.

1
répondu momeara 2009-12-01 04:07:38

vous pouvez base64-Encoder un guid. Cela répondra à tous vos critères sauf l'exigence "valeurs numériques seulement".

Vraiment, cependant, le correct la chose à faire ici est de laisser la base de données générer le numéro de commande. Cela peut signifier créer un ordre template enregistrement qui n'ont pas réellement un numéro de commande jusqu'à ce que l'utilisateur enregistre, il ou elle peut être en ajoutant la possibilité de créer vide (mais peut-être pas engagés) ordres.

1
répondu Joel Coehoorn 2009-12-01 04:08:03

utiliser les polynômes primitifs comme générateur de champs finis.

1
répondu Luka Rahne 2009-12-01 05:51:14

votre exigence de 10 chiffres est une énorme limite. Envisagez une approche en deux étapes.

  1. utilisez un guide
  2. préfixe le GUID avec un hachage à 10 chiffres (ou 5 ou 4 chiffres) du GUID.

Vous aurez plusieurs coups sur la valeur de hachage. Mais pas tant que ça. Le personnel du service client sera très facilement en mesure de déterminer quelle commande est en question sur la base d'informations supplémentaires fournies par le client.

1
répondu John 2009-12-01 19:02:05

la réponse simple à la plupart de vos points:

faites des six premiers chiffres un champ croissant de façon séquentielle, et ajoutez trois chiffres de hachage à la fin. Ou sept et deux, ou huit et un, selon le nombre de commandes que vous envisagez d'avoir à supporter.

cependant, vous devrez quand même appeler une fonction à l'arrière pour réserver un nouveau numéro de commande; sinon, il est impossible de garantir une non-collision, puisqu'il y a si peu de chiffres.

0
répondu gary 2009-12-01 05:00:04

nous faisons TTT-CCCCC-1A-n1.

  • T = Type de Circuit (D1E=DS1 EEL, D1U = DS1 UNE, etc.)
  • C = ID du client à 6 chiffres
  • 1 = premier emplacement du client
  • A = le premier circuit (A=1, B=2, etc) à cet endroit
  • N = type d'Ordre (N=Nouveau, X=Déconnecter, etc)
  • 1 = la première commande de ce genre pour ce circuit
0
répondu Josh 2009-12-01 06:09:24