registros orden obtener numero number muestra generar cadena and aleatorios aleatorio aleatoria sql-server tsql sql-server-2000

sql-server - orden - select aleatorio sql server



¿Cómo genero un número aleatorio para cada fila en un TSQL Select? (17)

Necesito un número aleatorio diferente para cada fila en mi tabla. El siguiente código aparentemente obvio usa el mismo valor aleatorio para cada fila.

SELECT table_name, RAND() magic_number FROM information_schema.tables

Me gustaría obtener un INT o un FLOTADOR de esto. El resto de la historia es que voy a utilizar este número aleatorio para crear un desplazamiento de fecha aleatorio a partir de una fecha conocida, por ejemplo, un desplazamiento de 1-14 días desde una fecha de inicio.

Esto es para Microsoft SQL Server 2000.


¿Tiene un valor entero en cada fila que podría pasar como semilla a la función RAND?

Para obtener un número entero entre 1 y 14 creo que esto funcionaría:

FLOOR( RAND(<yourseed>) * 14) + 1


Cuando se llama varias veces en un solo lote, rand () devuelve el mismo número.

Sugeriría usar convert ( varbinary , newid() ) como argumento semilla:

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

Se garantiza que newid() devolverá un valor diferente cada vez que se llame, incluso dentro del mismo lote, por lo que usarlo como semilla le pedirá a rand () dar un valor diferente cada vez.

Editado para obtener un número entero aleatorio de 1 a 14.


Eche un vistazo a SQL Server: establezca números aleatorios basados ​​en una explicación muy detallada.

Para resumir, el siguiente código genera un número aleatorio entre 0 y 13 inclusive con una distribución normalizada:

ABS(CHECKSUM(NewId())) % 14

Para cambiar su rango, solo cambie el número al final de la expresión. Tenga mucho cuidado si necesita un rango que incluya números positivos y negativos. Si lo haces mal, es posible contar doble el número 0.

Una pequeña advertencia para las nueces de matemáticas en la sala: hay un sesgo muy leve en este código. CHECKSUM() da como resultado números uniformes en todo el rango del tipo de datos Intl sql, o al menos tan cerca como pueden mostrar mis pruebas (el editor). Sin embargo, habrá cierto sesgo cuando CHECKSUM () produzca un número en el extremo superior de ese rango. Cada vez que obtenga un número entre el máximo entero posible y el último múltiplo exacto del tamaño de su rango deseado (14 en este caso) antes de ese máximo entero, esos resultados se verán favorecidos sobre la porción restante de su rango que no se puede producir a partir de Ese último múltiplo de 14.

Como ejemplo, imagine que el rango completo del tipo Int es solo 19. 19 es el mayor entero posible que puede contener. Cuando CHECKSUM () da como resultado 14-19, estos corresponden a los resultados 0-5. Esos números serían muy favorecidos en lugar de 6-13, porque CHECKSUM () tiene el doble de probabilidades de generarlos. Es más fácil demostrar esto visualmente. A continuación se muestra el conjunto completo de resultados posibles para nuestro rango entero imaginario:

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

Aquí puede ver que hay más posibilidades de producir algunos números que otros: sesgo. Afortunadamente, el rango real del tipo Int es mucho mayor ... tanto, que en la mayoría de los casos el sesgo es casi indetectable. Sin embargo, es algo que debe tener en cuenta si alguna vez se encuentra haciendo esto por un código de seguridad serio.


El problema que a veces tengo con la "Respuesta" seleccionada es que la distribución no siempre es uniforme. Si necesita una distribución muy equitativa de 1 a 14 aleatorias entre muchas filas, puede hacer algo como esto (mi base de datos tiene 511 tablas, así que esto funciona. Si tiene menos filas que el rango de números aleatorios, esto no funciona bien):

SELECT table_name, ntile(14) over(order by newId()) randomNumber FROM information_schema.tables

Esto hace lo contrario de las soluciones aleatorias normales en el sentido de que mantiene los números en secuencia y asigna al azar a la otra columna.

Recuerde, tengo 511 tablas en mi base de datos (que es pertinente solo para B / C que estamos seleccionando del esquema de información). Si tomo la consulta anterior y la coloco en una tabla temporal #X, y luego ejecuto esta consulta en los datos resultantes:

select randomNumber, count(*) ct from #X group by randomNumber

Obtengo este resultado, mostrándome que mi número aleatorio está MUY distribuido uniformemente entre las muchas filas:


Es tan fácil como:

DECLARE @rv FLOAT; SELECT @rv = rand();

Y esto pondrá un número aleatorio entre 0-99 en una tabla:

CREATE TABLE R ( Number int ) DECLARE @rv FLOAT; SELECT @rv = rand(); INSERT INTO dbo.R (Number) values((@rv * 100)); SELECT * FROM R


Generación de números aleatorios entre 1000 y 9999 inclusive:

FLOOR(RAND(CHECKSUM(NEWID()))*(9999-1000+1)+1000)

"+1" - para incluir valores de límite superior (9999 para el ejemplo anterior)


La función Rand () generará el mismo número aleatorio, si se utiliza en una consulta SELECT de tabla. Lo mismo se aplica si usas una semilla para la función Rand. Una forma alternativa de hacerlo, es usar esto:

SELECT ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]

Obtuve la información de here , lo que explica muy bien el problema.



Respondiendo a la pregunta anterior, pero esta respuesta no se ha proporcionado anteriormente, y esperamos que esto sea útil para alguien que encuentre estos resultados a través de un motor de búsqueda.

Con SQL Server 2008, se ha introducido una nueva función, CRYPT_GEN_RANDOM(8) , que utiliza CryptoAPI para producir un número aleatorio criptográficamente fuerte, devuelto como VARBINARY(8000) . Aquí está la página de documentación: https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sql

Entonces, para obtener un número aleatorio, simplemente puede llamar a la función y convertirla al tipo necesario:

select CAST(CRYPT_GEN_RANDOM(8) AS bigint)

o para obtener una float entre -1 y +1, podrías hacer algo como esto:

select CAST(CRYPT_GEN_RANDOM(8) AS bigint) % 1000000000 / 1000000000.0


Si necesita conservar su semilla para que genere los "mismos" datos aleatorios cada vez, puede hacer lo siguiente:

1. Crea una vista que devuelva seleccionar rand ()

if object_id(''cr_sample_randView'') is not null begin drop view cr_sample_randView end go create view cr_sample_randView as select rand() as random_number go

2. Cree un UDF que seleccione el valor de la vista.

if object_id(''cr_sample_fnPerRowRand'') is not null begin drop function cr_sample_fnPerRowRand end go create function cr_sample_fnPerRowRand() returns float as begin declare @returnValue float select @returnValue = random_number from cr_sample_randView return @returnValue end go

3. Antes de seleccionar sus datos, coloque la función rand () y luego use el UDF en su declaración de selección.

select rand(200); -- see the rand() function with cte(id) as (select row_number() over(order by object_id) from sys.all_objects) select id, dbo.cr_sample_fnPerRowRand() from cte where id <= 1000 -- limit the results to 1000 random numbers


Si no necesita que sea un entero, pero cualquier identificador único aleatorio, puede usar newid()

SELECT table_name, newid() magic_number FROM information_schema.tables


intente usar un valor semilla en RAND (seedInt). RAND () solo se ejecutará una vez por enunciado, por eso ve el mismo número cada vez.


seleccione newid()

o posiblemente este seleccione binary_checksum (newid ())


DROP VIEW IF EXISTS vwGetNewNumber; GO Create View vwGetNewNumber as Select CAST(RAND(CHECKSUM(NEWID())) * 62 as INT) + 1 as NextID, ''abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ''as alpha_num; ---------------CTDE_GENERATE_PUBLIC_KEY ----------------- DROP FUNCTION IF EXISTS CTDE_GENERATE_PUBLIC_KEY; GO create function CTDE_GENERATE_PUBLIC_KEY() RETURNS NVARCHAR(32) AS BEGIN DECLARE @private_key NVARCHAR(32); set @private_key = dbo.CTDE_GENERATE_32_BIT_KEY(); return @private_key; END; go ---------------CTDE_GENERATE_32_BIT_KEY ----------------- DROP FUNCTION IF EXISTS CTDE_GENERATE_32_BIT_KEY; GO CREATE function CTDE_GENERATE_32_BIT_KEY() RETURNS NVARCHAR(32) AS BEGIN DECLARE @public_key NVARCHAR(32); DECLARE @alpha_num NVARCHAR(62); DECLARE @start_index INT = 0; DECLARE @i INT = 0; select top 1 @alpha_num = alpha_num from vwGetNewNumber; WHILE @i < 32 BEGIN select top 1 @start_index = NextID from vwGetNewNumber; set @public_key = concat (substring(@alpha_num,@start_index,1),@public_key); set @i = @i + 1; END; return @public_key; END; select dbo.CTDE_GENERATE_PUBLIC_KEY() public_key;


RAND(CHECKSUM(NEWID()))

Lo anterior generará un (pseudo) número aleatorio entre 0 y 1, exclusivo. Si se usa en una selección, porque el valor de semilla cambia para cada fila, generará un nuevo número aleatorio para cada fila (sin embargo, no se garantiza que genere un número único por fila).

Ejemplo cuando se combina con un límite superior de 10 (produce números 1 - 10):

CAST(RAND(CHECKSUM(NEWID())) * 10 as INT) + 1

Documentación Transact-SQL:

  1. CAST() : https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql
  2. RAND() : http://msdn.microsoft.com/en-us/library/ms177610.aspx
  3. CHECKSUM() : http://msdn.microsoft.com/en-us/library/ms189788.aspx
  4. NEWID() : https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql

select ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) as [Randomizer]

siempre me ha funcionado


select round(rand(checksum(newid()))*(10)+20,2)

Aquí, el número aleatorio vendrá entre 20 y 30. La round dará un máximo de dos decimales.

Si quieres números negativos puedes hacerlo con

select round(rand(checksum(newid()))*(10)-60,2)

Entonces el valor mínimo será -60 y el máximo será -50.