Était-ce utile?

La solution

Pourquoi se contenter de la distribution d'énergie-droit lorsque vous pouvez tirer de la distribution réelle?

Je vous suggère de modifier la table LastNames pour inclure une colonne numérique qui contiendrait une valeur numérique représentant le nombre réel de indivuduals avec un nom qui est plus fréquent. Vous aurez probablement besoin d'un numéro sur une échelle plus petite, mais proportionnelle, disons, peut-être 10 000 pour chaque pour cent de la représentation.

La liste serait alors ressembler à:
(Autre que les 3 noms mentionnés dans la question, je devine sur White, Johnson et al)

Smith          0   
White     10,060
Johnson   19,123
Williams  28,456
...
Sanders  200,987
..
Alderink 999,997

Et la sélection de nom serait

SELECT TOP 1 [LastName]
FROM [LastNames] as LN
WHERE LN.[number_described_above] < ROUND(100000 * RAND(), 0)
ORDER BY [number_described_above] DESC

C'est de choisir le prénom dont le nombre ne dépasse pas le nombre aléatoire [distribution uniforme]. Notez comment la requête, les utilisations moins et l'ordre dans desc pour -ending; cette garantie de volonté que la toute première entrée (Smith) est ramassé. L'alternative serait de commencer la série avec Smith à 10060 plutôt que zéro et à rejeter le tirage au sort inférieur à cette valeur.

En dehors de la question de la gestion de délimitation (commençant à zéro au lieu de 10060) mentionné ci-dessus, cette solution, en même temps que les deux autres réponses à ce jour, sont les mêmes que celle suggérée dans dmckee » s réponse à la question mentionnée dans cette question. Essentiellement, l'idée est d'utiliser le CDF ( Fonction cumulative de distribution ).


Modifier :
Si vous insistez sur l'utilisation de une fonction mathématique plutôt que la distribution réelle , ce qui suit devrait fournir une fonction de la loi de puissance qui serait en quelque sorte de traduire la forme de la distribution réelle « longue queue ». Vous pouvez wan à modifier la valeur @PwrCoef (qui n'a pas besoin BTW un entier), essentiellement plus le coeficient, plus biaisé au début de la liste est la fonction.

DECLARE @PwrCoef INT
SET @PwrCoef = 2
SELECT 88799 - ROUND(POWER(POWER(88799.0, @PwrCoef) * RAND(), 1.0/@PwrCoef), 0)

Notes:
  - extra » .0" dans la fonction ci-dessus sont importants pour forcer SQL pour effectuer des opérations flottantes plutôt que des opérations entières
.   - la raison pour laquelle nous soustrayons le calcul de la puissance de 88799 est que la distribution du calcul est telle que plus un nombre est plus proche de la fin de notre échelle, plus il est probable à tirer. La liste des noms de famille étant classée dans l'ordre inverse (les noms les plus probables en premier), nous avons besoin de ce soustractions.

En supposant une puissance de, disons, 3 la requête serait alors ressembler à

SELECT [LastName]
FROM [LastNames] as LN
WHERE LN.[Rank]
     = 88799 - ROUND(POWER(POWER(88799.0, 3) * RAND(), 1.0/3), 0)

Quelle est la requête de la question à l'exception de la dernière ligne.

Re-Edit :
En regardant la distribution réelle, comme cela apparaît dans les données du recensement, la courbe est extrêmement raide et nécessiterait un coefficient de puissance très grand, ce qui provoquerait des débordements et / ou des erreurs d'arrondi d'extrêmes dans la naïve formule ci-dessus.
Une approche plus sensée peut être d'opérer dans plusieurs niveaux à savoir d'effectuer un nombre égal de tirages dans chacun des, disons, trois tiers (ou quatre trimestres ou ...) de la distribution cumulée; Dans chacune de ces listes de pièces, nous tirer en utilisant une fonction de la loi de puissance, peut-être avec le même coeficient, mais avec des gammes différentes.
Par exemple
En supposant que tiers, la liste se divise comme suit:

  • Premier tiers = 425 noms, de Smith à Alvarado
  • Deuxième tiers = 6,277 noms, de à Gainer
  • dernier tiers = 82,097 noms, de Frisby à la fin

Si nous devions besoin, disons, 1000 noms, nous tirerais 334 du troisième sommet de la liste, 333 du deuxième tiers et 333 du dernier tiers.
Pour chacun des tiers nous utiliserions une formule similaire, peut-être avec une plus grande coeficient de puissance pour le premier tiers (Were Were sont vraiment intéressés à favoriser les noms précédents dans la liste, et aussi où le parent les fréquences sont plus statistiquement pertinentes). Les trois requêtes de sélection pourrait ressembler à ce qui suit:

-- Random Drawing of a single Name in top third
--   Power Coef = 12
SELECT [LastName]
FROM [LastNames] as LN
WHERE LN.[Rank]
     =  425 - ROUND(POWER(POWER(425.0, 12) * RAND(), 1.0/12), 0)

-- Second third; Power Coef = 7
...
WHERE LN.[Rank]
     =  (425 + 6277) - ROUND(POWER(POWER(6277.0, 7) * RAND(), 1.0/7), 0)

-- Bottom third; Power Coef = 4
...
WHERE LN.[Rank]
     =  (425 + 6277 + 82097) - ROUND(POWER(POWER(82097.0, 4) * RAND(), 1.0/4), 0)

Autres conseils

Au lieu de stocker le pdf comme rang, stocker le CDF (la somme de toutes les fréquences jusqu'à ce que le nom, à partir de Aldekirk).

Ensuite, modifiez votre sélection pour récupérer la première LN avec plus de rang que votre résultat de la formule.

Je lis la question « Je dois obtenir un flux de noms qui refléteront la fréquence des noms de famille du recensement américain de 1990 »

Je pourrais avoir lu la question un peu différemment que les autres suggestions et même si une réponse a été acceptée, et même par réponse est, je vais apporter mon expérience avec les noms de famille de recensement.

J'avais téléchargé les mêmes données du recensement de 1990. Mon objectif était de produire un grand nombre de noms à être soumis aux essais de recherche au cours des tests de performance d'une application de dossier médical. J'inséré les noms de famille et le pourcentage de la fréquence dans une table. J'ai ajouté une colonne et il remplit avec un entier qui était le produit des « noms total requis fréquence * ». Les données de fréquence du recensement ne correspondait pas exactement à 100% donc mon nombre total de noms a également été un peu court de l'exigence. J'ai pu corriger le nombre en sélectionnant des noms aléatoires dans la liste et en augmentant leur nombre jusqu'à ce que j'ai eu exactement le nombre requis, le nombre ajouté au hasard jamais ammounted à plus de 0,05% du total de 10 millions.

Je généré 10 millions de nombres aléatoires dans la plage de 1 à 88799. Avec chaque nombre aléatoire je choisirais ce nom dans la liste et décrémenter le compteur de ce nom. Mon approche était de simuler le traitement d'un jeu de cartes, sauf ma plate-forme avait beaucoup de cartes distinctes et un certain nombre varing de chaque carte.

Avez-vous stockez les fréquences réelles avec les rangs?

Conversion l'algèbre de cette réponse acceptée à MySQL est la peine non, si vous savez quelles sont les valeurs à utiliser pour n. y serait ce que vous avez actuellement ROUND(88799 * RAND(), 0) et x0,x1 = 1,88799 Je pense que, bien que je pourrais s'y méprendre. Le seul opérateur de mathématiques non standard impliqués dans une perspective T-SQL est ^ qui est juste POWER(x,y) == x^y.

scroll top