Générer une valeur int aléatoire de 3 à 6


101

Est-il possible dans Microsoft SQL Server de générer une valeur int aléatoire de Min à Max (exemple 3-9, 15-99, etc.)

Je sais, je peux générer de 0 à Max, mais comment augmenter la frontière Min?

Cette requête génère une valeur aléatoire de 1 à 6. Vous devez la changer de 3 à 6.

SELECT table_name, 1.0 + floor(6 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

Ajouté 5 sec plus tard :

Question stupide, désolé ...

SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

1
La réponse que vous avez là ne fonctionne que si vous avez des autorisations de type administrateur sur la table. La façon dont j'ai contourné cela a été d'utiliser la clé primaire sur le terrain comme graine. La distribution n'était pas géniale, mais elle a servi le but.
Shadow

Réponses:


196

Cela génère un nombre aléatoire entre 0 et 9

SELECT ABS(CHECKSUM(NEWID()) % 10)

1 à 6

SELECT ABS(CHECKSUM(NEWID()) % 6) + 1

3 à 6

SELECT ABS(CHECKSUM(NEWID()) % 4) + 3

Dynamique (basé sur le commentaire d'Eilert Hjelmeseths)

SELECT ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min

Mis à jour en fonction des commentaires:

  • NEWID génère une chaîne aléatoire (pour chaque ligne en retour)
  • CHECKSUM prend la valeur de la chaîne et crée un nombre
  • modulus ( %) divise par ce nombre et renvoie le reste (ce qui signifie que la valeur maximale est un de moins que le nombre que vous utilisez)
  • ABS change les résultats négatifs en positifs
  • puis ajoutez un au résultat pour éliminer 0 résultat (pour simuler un jet de dés)

2
cela m'a beaucoup aidé! rappelez-vous simplement que si vous essayez de générer des clés aléatoires pour des insertions en masse, cela peut provoquer des doublons et certaines instructions échoueront. mais merci!
Niklas

3
Et si je dois générer un nombre aléatoire entre 1 et 27? ie gamme supérieure à 9?
somegeek

4
Si je suis la logique, il semble que ce réglage vous permettra de définir facilement la plage de manière dynamique. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Quelques tests de ma part ont donné de bons résultats. Si c'est effectivement exact, je pense que cette réponse pourrait être légèrement améliorée en l'incluant.
Eilert Hjelmeseth

13

Je vois que vous avez ajouté une réponse à votre question dans SQL Server 2008 que vous pouvez également faire

SELECT 3 + CRYPT_GEN_RANDOM(1) % 4 /*Random number between 3 and 6*/ 
FROM ...

Quelques inconvénients de cette méthode sont

  1. C'est plus lent que la NEWID()méthode
  2. Même s'il est évalué une fois par ligne, l'optimiseur de requêtes ne s'en rend pas compte, ce qui peut conduire à des résultats étranges .

mais je pensais juste l'ajouter comme une autre option.


1
@ FSou1 - Oui. Je pense que CRYPT_GEN_RANDOMc'est vraiment destiné aux situations où vous avez besoin d'un nombre pseudo aléatoire plus sécurisé cryptographiquement.
Martin Smith

7

Tu peux le faire:

DECLARE @maxval TINYINT, @minval TINYINT
select @maxval=24,@minval=5

SELECT CAST(((@maxval + 1) - @minval) *
    RAND(CHECKSUM(NEWID())) + @minval AS TINYINT)

Et cela a été pris directement à partir de ce lien , je ne sais pas vraiment comment donner le crédit approprié pour cette réponse.


5

Sympa et simple, du site de Pinal Dave:

http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/

DECLARE @Random INT;
DECLARE @Upper INT;
DECLARE @Lower INT
SET @Lower = 3 ---- The lowest random number
SET @Upper = 7 ---- One more than the highest random number
SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random

(J'ai fait une légère modification au @ Upper- pour inclure le nombre supérieur, ajouté 1.)


J'ai vu cet exemple dans une autre publication. Il ne fournit pas de distribution aléatoire. Par exemple, Lower est 1 et Upper est 11, donc je veux des nombres aléatoires de 1 à 10. Le 1 et le 10 obtiennent la moitié des occurrences comme 2-8. Allez le tester.
nanonerd

4

Simplement:

DECLARE @MIN INT=3; --We define minimum value, it can be generated.
DECLARE @MAX INT=6; --We define maximum value, it can be generated.

SELECT @MIN+FLOOR((@MAX-@MIN+1)*RAND(CONVERT(VARBINARY,NEWID()))); --And then this T-SQL snippet generates an integer between minimum and maximum integer values.

Vous pouvez changer et éditer ce code selon vos besoins.


1
Bien que cet extrait de code soit le bienvenu et puisse fournir une aide, il serait grandement amélioré s'il incluait une explication de la façon dont il répond à la question. Sans cela, votre réponse a beaucoup moins de valeur éducative - rappelez-vous que vous répondez à la question pour les lecteurs à l'avenir, pas seulement pour la personne qui la pose maintenant! Veuillez modifier votre réponse pour ajouter une explication et donner une indication des limites et des hypothèses applicables.
Toby Speight

4

Voici la simple et unique ligne de code

Pour cela, utilisez la fonction SQL Inbuild RAND () .

Voici la formule pour générer un nombre aléatoire entre deux nombres (RETURN INT Range)

Ici, a est votre premier nombre (min) et b est le deuxième nombre (max) de la plage

SELECT FLOOR(RAND()*(b-a)+a)

Remarque: vous pouvez également utiliser la fonction CAST ou CONVERT pour obtenir le numéro de plage INT.

(CAST (RAND () * (25-10) +10 AS INT))

Exemple:

SELECT FLOOR(RAND()*(25-10)+10);

Voici la formule pour générer un nombre aléatoire entre deux nombres (RETURN DECIMAL Range)

SELECT RAND()*(b-a)+a;

Exemple:

SELECT RAND()*(25-10)+10;

Plus de détails, vérifiez ceci: https://www.techonthenet.com/sql_server/functions/rand.php


1
Notez que, comme mentionné dans l'article lié, cela ne générera pas réellement de valeurs = Max. Pour ce faire, par exemple pour les valeurs> = 10 et <= 25, vous auriez besoin de SELECT FLOOR (RAND () * (25-10 + 1)) + 10
Shaun

1
SELECT ROUND((6 - 3 * RAND()), 0)

2
La chance d'obtenir un numéro sur l'autre n'est pas également répartie. Vérifiez la sortie de ceci: SELECT ROUND((6 - 3 * 0.16), 0) SELECT ROUND((6 - 3 * 0.17), 0) SELECT ROUND((6 - 3 * 0.5), 0) SELECT ROUND((6 - 3 * 0.51), 0) SELECT ROUND((6 - 3 * 0.83), 0) SELECT ROUND((6 - 3 * 0.84), 0) Montre que 16% de changement pour 6, ~ 34% c'est 5, ~ 34% c'est 4 et ~ 16% c'est 3.
Mike de Klerk

la troncature est supérieure à l'arrondi
MichaelChirico

0

Réponse de Lamak en fonction:

-- Create RANDBETWEEN function
-- Usage: SELECT dbo.RANDBETWEEN(0,9,RAND(CHECKSUM(NEWID())))
CREATE FUNCTION dbo.RANDBETWEEN(@minval TINYINT, @maxval TINYINT, @random NUMERIC(18,10))
RETURNS TINYINT
AS
BEGIN
  RETURN (SELECT CAST(((@maxval + 1) - @minval) * @random + @minval AS TINYINT))
END
GO

0
DECLARE @min INT = 3;
DECLARE @max INT = 6;
SELECT @min + ROUND(RAND() * (@max - @min), 0);

Pas à pas

DECLARE @min INT = 3;
DECLARE @max INT = 6;

DECLARE @rand DECIMAL(19,4) = RAND();
DECLARE @difference INT = @max - @min;
DECLARE @chunk INT = ROUND(@rand * @difference, 0);
DECLARE @result INT = @min + @chunk; 
SELECT @result;

Notez qu'une fonction définie par l'utilisateur ne permet donc pas l'utilisation de RAND (). Une solution de contournement pour cela (source: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ) consiste à créer d'abord une vue.

CREATE VIEW [dbo].[vw_RandomSeed]
AS
SELECT        RAND() AS seed

puis créez la fonction aléatoire

CREATE FUNCTION udf_RandomNumberBetween
(
    @min INT,
    @max INT
)
RETURNS INT
AS
BEGIN
    RETURN @min + ROUND((SELECT TOP 1 seed FROM vw_RandomSeed) * (@max - @min), 0);
END

0

En général:

select rand()*(@upper-@lower)+@lower;

Pour votre question:

select rand()*(6-3)+3;

<=>

select rand()*3+3;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.