Generar valor int aleatorio de 3 a 6

101

¿Es posible en Microsoft SQL Server generar un valor int aleatorio de Min a Max (3-9 ejemplo, 15-99, etc.)

Lo sé, puedo generar de 0 a Max, pero ¿cómo aumentar el borde mínimo?

Esta consulta genera un valor aleatorio de 1 a 6. Necesita cambiarlo de 3 a 6.

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

Agregado 5 segundos después :

Pregunta estúpida, lo siento ...

SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables
FSou1
fuente
1
La respuesta que tiene allí solo funciona si tiene permisos de tipo de administrador en la mesa. La forma en que solucioné esto fue utilizando la clave principal en el campo como semilla. La distribución no fue brillante, pero cumplió su propósito.
Shadow

Respuestas:

196

Esto genera un número aleatorio entre 0-9

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

1 a 6

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

3 a 6

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

Dinámico (basado en el comentario de Eilert Hjelmeseth)

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

Actualizado según los comentarios:

  • NEWID genera una cadena aleatoria (para cada fila a cambio)
  • CHECKSUM toma el valor de la cadena y crea un número
  • modulus ( %) divide por ese número y devuelve el resto (lo que significa que el valor máximo es uno menos que el número que usa)
  • ABS cambia los resultados negativos a positivos
  • luego agregue uno al resultado para eliminar 0 resultados (para simular una tirada de dados)
orgtigger
fuente
2
¡esto me ayudó muchísimo! solo recuerde que si está intentando generar claves aleatorias para inserciones masivas, esto puede causar duplicados y algunas declaraciones fallarán. ¡pero gracias!
Niklas
3
¿Qué pasa si tengo que generar un número aleatorio entre 1 y 27? es decir, rango superior a 9?
somegeek
4
Si sigo la lógica, parece que este ajuste le permitirá establecer con precisión el rango de forma dinámica y fácil. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Algunas pruebas de mi parte dieron buenos resultados. Si es realmente precisa, creo que esta respuesta podría mejorarse ligeramente incluyéndola.
Eilert Hjelmeseth
13

Veo que ha agregado una respuesta a su pregunta en SQL Server 2008 que también puede hacer

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

Un par de desventajas de este método son

  1. Esto es más lento que el NEWID()método.
  2. Aunque se evalúa una vez por fila, el optimizador de consultas no se da cuenta de esto, lo que puede generar resultados extraños .

pero pensé en agregarlo como otra opción.

Martin Smith
fuente
1
@ FSou1 - Sí. Creo que CRYPT_GEN_RANDOMestá realmente destinado a situaciones en las que necesitas un número pseudo aleatorio criptográficamente más seguro.
Martin Smith
7

Puedes hacerlo:

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

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

Y eso fue tomado directamente de este enlace , realmente no sé cómo dar el crédito adecuado por esta respuesta.

Lamak
fuente
5

Agradable y simple, del sitio 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

(Hice un pequeño cambio en @ Upper- para incluir el número superior, agregado 1.)

Adrian Carr
fuente
Vi este ejemplo en otra publicación. No proporciona una distribución aleatoria. Por ejemplo, Lower es 1 y Upper es 11, por lo que quiero números aleatorios del 1 al 10. El 1 y el 10 obtienen la mitad de las ocurrencias como 2-8. Ve y pruébalo.
nanonerd
4

Simplemente:

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.

Puede cambiar y editar este código según sus necesidades.

MERT DOĞAN
fuente
1
Si bien este fragmento de código es bienvenido y puede proporcionar algo de ayuda, se mejoraría mucho si incluyera una explicación de cómo aborda la pregunta. Sin eso, su respuesta tiene mucho menos valor educativo; recuerde que está respondiendo la pregunta para los lectores en el futuro, ¡no solo la persona que pregunta ahora! Por favor, editar su respuesta para agregar explicación y dar una indicación de lo que se aplican limitaciones y supuestos.
Toby Speight
4

Aquí está la línea de código simple y única

Para ello, utilice la función SQL Inbuild RAND () .

Aquí está la fórmula para generar un número aleatorio entre dos números (RETORNO INT Rango)

Aquí a es su primer número (mínimo) yb es el segundo número (máximo) en el rango

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

Nota: También puede usar la función CAST o CONVERT para obtener el número de rango INT.

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

Ejemplo:

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

Aquí está la fórmula para generar un número aleatorio entre dos números (RETORNO DECIMAL Rango)

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

Ejemplo:

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

Más detalles verifique esto: https://www.techonthenet.com/sql_server/functions/rand.php

Manjunath Bilwar
fuente
1
Tenga en cuenta que, como se menciona en el artículo vinculado, esto no generará valores = Máx. Para hacer esto, por ejemplo, para valores> = 10 y <= 25, necesitaría SELECT FLOOR (RAND () * (25-10 + 1)) + 10
Shaun
1
SELECT ROUND((6 - 3 * RAND()), 0)
greg121
fuente
2
La posibilidad de obtener un número sobre el otro no se distribuye por igual. Verifique el resultado de esto: 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) muestra que el 16% cambia para 6, ~ 34% es 5, ~ 34% es 4 y ~ 16% es 3.
Mike de Klerk
truncar es superior al redondeo
MichaelChirico
0

La respuesta de Lamak como función:

-- 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
AndreFeijo
fuente
0
DECLARE @min INT = 3;
DECLARE @max INT = 6;
SELECT @min + ROUND(RAND() * (@max - @min), 0);

Paso a paso

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;

Tenga en cuenta que una función definida por el usuario no permite el uso de RAND (). Una solución alternativa para esto (fuente: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ) es crear una vista primero.

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

y luego crea la función aleatoria

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
Mike de Klerk
fuente
0

En general:

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

Para tu pregunta:

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

<=>

select rand()*3+3;
Zeinab
fuente