Jetez un coup d'œil à SQL Server - Numéros aléatoires basés sur un ensemble qui contient une explication très détaillée.
Pour résumer, le code suivant génère un nombre aléatoire compris entre 0 et 13 inclus avec une distribution uniforme :
ABS(CHECKSUM(NewId())) % 14
Pour modifier votre plage, il suffit de changer le nombre à la fin de l'expression. Faites très attention si vous avez besoin d'une plage qui inclut à la fois des nombres positifs et négatifs. Si vous vous y prenez mal, il est possible de compter deux fois le nombre 0.
Un petit avertissement pour les fous de maths dans la salle : il y a un très léger biais dans ce code. CHECKSUM()
donne des résultats uniformes sur toute la plage du type de données sql Int, ou du moins aussi proches que mes tests (ceux de l'éditeur) peuvent le montrer. Cependant, il y aura un certain biais lorsque CHECKSUM() produit un nombre à l'extrémité supérieure de cette plage. Chaque fois que vous obtenez un nombre entre le nombre entier maximum possible et le dernier multiple exact de la taille de votre plage souhaitée (14 dans ce cas) avant ce nombre entier maximum, ces résultats sont favorisés par rapport à la partie restante de votre plage qui ne peut pas être produite à partir de ce dernier multiple de 14.
Par exemple, imaginez que la plage entière du type Int est seulement 19. 19 est le plus grand nombre entier possible que vous pouvez détenir. Lorsque CHECKSUM() donne un résultat de 14 à 19, cela correspond aux résultats 0 à 5. Ces nombres seraient lourdement favorisé par rapport à 6-13, car CHECKSUM() a deux fois plus de chances de les générer. Il est plus facile de démontrer cela visuellement. Vous trouverez ci-dessous l'ensemble des résultats possibles pour notre gamme d'entiers imaginaires :
Checksum Integer: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Range Result: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 0 1 2 3 4 5
Vous pouvez voir ici qu'il y a plus de chances de produire certains nombres que d'autres : le biais. Heureusement, l'étendue réelle du type Int est de beaucoup plus large... à tel point que dans la plupart des cas, le biais est presque indétectable. Cependant, c'est quelque chose dont il faut être conscient si vous vous retrouvez un jour à faire cela pour un code de sécurité sérieux.
6 votes
Existe-t-il une solution qui n'utilise pas NEWID() ? Je veux pouvoir générer la même séquence de nombres aléatoires pour une graine donnée.
2 votes
@Rory Posez cette question comme une nouvelle question, elle recevra plus d'attention. (Ma réponse serait d'utiliser des tables fixes de nombres aléatoires, par exemple ce célèbre ensemble standard de nombres aléatoires : rand.org/pubs/monograph_reports/MR1418/index.html )
3 votes
Regardez ! RAND (Transact-SQL)
1 votes
RAND a été introduit en 2005, cette question a été posée en 2009, quelles organisations utilisaient encore SQL 2000 parce que c'était la 1ère version suffisamment bonne pour être utilisée à jamais.
1 votes
Rory MacLeod a demandé : "Existe-t-il une solution qui n'utilise pas NEWID() ? Je veux être capable de générer la même séquence de nombres aléatoires pour une graine donnée." La réponse est oui, mais c'est un peu alambiqué. 1. Créer une vue qui renvoie select rand() 2. Créer un UDF qui sélectionne la valeur de la vue. 3. Avant de sélectionner vos données, ensemencez la fonction rand(). 4. Utilisez l'UDF dans votre instruction select. Je vais poster un exemple complet ci-dessous