J'ai besoin d'un nombre aléatoire différent pour chaque ligne de ma table. Le code apparemment évident suivant utilise la même valeur aléatoire pour chaque ligne.
SELECT table_name, RAND() magic_number
FROM information_schema.tables
J'aimerais retirer un INT ou un FLOAT de cela. Le reste de l'histoire est que je vais utiliser ce nombre aléatoire pour créer un décalage de date aléatoire à partir d'une date connue, par exemple 1-14 jours de décalage à partir d'une date de début.
C'est pour Microsoft SQL Server 2000.
sql-server
tsql
sql-server-2000
MatthewMartin
la source
la source
Réponses:
Jetez un œil à SQL Server - Définir des nombres aléatoires basés sur 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:
Pour changer votre plage, changez simplement le nombre à la fin de l'expression. Soyez extrêmement prudent si vous avez besoin d'une plage comprenant à la fois des nombres positifs et négatifs. Si vous le faites mal, il est possible de compter deux fois le nombre 0.
Un petit avertissement pour les écrous mathématiques dans la salle: il y a un très léger biais dans ce code.
CHECKSUM()
résulte en des nombres qui sont uniformes sur toute la plage du type de données sql Int, ou au moins aussi proches que mes tests (l'éditeur) peuvent le montrer. Cependant, il y aura un certain biais lorsque CHECKSUM () produit un nombre tout en haut de cette plage. Chaque fois que vous obtenez un nombre entre l'entier maximum possible et le dernier multiple exact de la taille de votre plage souhaitée (14 dans ce cas) avant cet 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 n'est que de 19. 19 est le plus grand entier possible que vous pouvez contenir. Lorsque CHECKSUM () donne 14-19, cela correspond aux résultats 0-5. Ces chiffres seraient fortement favorisés sur 6-13, car CHECKSUM () est deux fois plus susceptible de les générer. Il est plus facile de le démontrer visuellement. Voici l'ensemble complet des résultats possibles pour notre gamme entière imaginaire:
Vous pouvez voir ici qu'il y a plus de chances de produire certains nombres que d'autres: le biais. Heureusement, la plage réelle du type Int est beaucoup plus grande ... si bien que dans la plupart des cas, le biais est presque indétectable. Cependant, c'est quelque chose à savoir si vous vous retrouvez à le faire pour un code de sécurité sérieux.
la source
Lorsqu'il est appelé plusieurs fois dans un même lot, rand () renvoie le même numéro.
Je suggère d'utiliser convert (
varbinary
,newid()
) comme argument de départ:newid()
est garanti pour renvoyer une valeur différente chaque fois qu'il est appelé, même dans le même lot, donc l'utiliser comme une graine invitera rand () à donner une valeur différente à chaque fois.Modifié pour obtenir un nombre entier aléatoire de 1 à 14.
la source
Ce qui précède va générer un nombre (pseudo-) aléatoire entre 0 et 1, exclusif. S'il est utilisé dans une sélection, car la valeur de départ change pour chaque ligne, il générera un nouveau nombre aléatoire pour chaque ligne (il n'est pas garanti de générer un nombre unique par ligne cependant).
Exemple lorsqu'il est combiné avec une limite supérieure de 10 (produit les nombres 1 à 10):
Documentation Transact-SQL:
CAST()
: https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sqlRAND()
: http://msdn.microsoft.com/en-us/library/ms177610.aspxCHECKSUM()
: http://msdn.microsoft.com/en-us/library/ms189788.aspxNEWID()
: https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sqlla source
Génération de nombres aléatoires entre 1000 et 9999 inclus:
"+1" - pour inclure les valeurs de limite supérieure (9999 pour l'exemple précédent)
la source
FLOOR(RAND(CHECKSUM(NEWID()))*(10000-1000)+1000)
Répondre à l'ancienne question, mais cette réponse n'a pas été fournie précédemment, et j'espère que cela sera utile pour quelqu'un qui trouve ces résultats via un moteur de recherche.
Avec SQL Server 2008, une nouvelle fonction a été introduite,
CRYPT_GEN_RANDOM(8)
qui utilise CryptoAPI pour produire un nombre aléatoire cryptographiquement fort, renvoyé sous la formeVARBINARY(8000)
. Voici la page de documentation: https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sqlDonc, pour obtenir un nombre aléatoire, vous pouvez simplement appeler la fonction et la convertir en le type nécessaire:
ou pour obtenir un
float
entre -1 et +1, vous pouvez faire quelque chose comme ceci:la source
La fonction Rand () générera le même nombre aléatoire, si elle est utilisée dans une requête SELECT de table. Il en va de même si vous utilisez une valeur de départ pour la fonction Rand. Une autre façon de procéder consiste à utiliser ceci:
J'ai obtenu les informations d' ici , ce qui explique très bien le problème.
la source
Avez-vous une valeur entière dans chaque ligne que vous pourriez passer comme valeur de départ à la fonction RAND?
Pour obtenir un entier entre 1 et 14, je pense que cela fonctionnerait:
la source
RAND(<seed>)
semble ne pas être très aléatoire pour des changements mineurs<seed>
. Par exemple, un test rapide que j'ai fait: j'ai laissé<seed>
être 184380, 184383, 184386, et lesRAND(<seed>)
valeurs correspondantes étaient: 0,14912, 0,14917, 0,14923.RAND(<seed>)*100000) - FLOOR(RAND(<seed>)*100000)
Si vous devez conserver votre graine afin qu'elle génère à chaque fois les "mêmes" données aléatoires, vous pouvez procéder comme suit:
1. Créez une vue qui renvoie select rand ()
2. Créez un UDF qui sélectionne la valeur dans la vue.
3. Avant de sélectionner vos données, amorcez la fonction rand (), puis utilisez l'UDF dans votre instruction select.
la source
essayez d'utiliser une valeur de départ dans le RAND (seedInt). RAND () ne s'exécutera qu'une fois par instruction, c'est pourquoi vous voyez le même nombre à chaque fois.
la source
RIGHT(CONVERT(BIGINT, RAND(RecNo) * 1000000000000), 2)
(note: je voisRIGHT
implicitement convertir leBIGINT
enCHAR
, mais pour être rigoureux, vous en auriez un autreCONVERT
).Si vous n'avez pas besoin que ce soit un entier, mais tout identifiant unique aléatoire, vous pouvez utiliser
newid()
la source
Vous devez appeler RAND () pour chaque ligne. Voici un bon exemple
https://web.archive.org/web/20090216200320/http://dotnet.org.za/calmyourself/archive/2007/04/13/sql-rand-trap-same-value-per-row.aspx
la source
RAND()
dans une vue, met uneSELECT
de cette vue dans une fonction, puis appelle la fonction de n'importe où. Intelligent.Ici, le nombre aléatoire entrera entre 20 et 30.
round
donnera au maximum deux décimales.Si vous voulez des nombres négatifs, vous pouvez le faire avec
Ensuite, la valeur min sera -60 et max sera -50.
la source
C'est aussi simple que:
Et cela mettra un nombre aléatoire entre 0 et 99 dans une table:
la source
Le problème que j'ai parfois avec la «réponse» sélectionnée est que la distribution n'est pas toujours uniforme. Si vous avez besoin d'une distribution très uniforme de 1 à 14 au hasard parmi de nombreuses lignes, vous pouvez faire quelque chose comme ça (ma base de données a 511 tables, donc cela fonctionne. Si vous avez moins de lignes que vous n'en avez au hasard, cela ne fonctionne pas. bien):
Ce type d'opération fait le contraire des solutions aléatoires normales dans le sens où il maintient les nombres séquencés et randomise l'autre colonne.
Rappelez-vous, j'ai 511 tables dans ma base de données (ce qui n'est pertinent que b / c que nous sélectionnons dans le schéma_information). Si je prends la requête précédente et la place dans une table temporaire #X, puis exécute cette requête sur les données résultantes:
J'obtiens ce résultat, me montrant que mon nombre aléatoire est TRÈS uniformément réparti entre les nombreuses lignes:
la source
a toujours travaillé pour moi
la source
Utilisez newid ()
ou peut-être cela
la source
la source
Essaye ça:
Où
a
est le nombre inférieur etb
le nombre supérieurla source
Nombre compris entre 1 et 10.
la source