2010-09-22 22 views
5

Quiero elegir aleatoriamente un valor de un pequeño rango de enteros (menos de 200). Como alternativa aCRYPT_GEN_RANDOM extraños efectos

SELECT RAND() 

Estoy intentando utilizar

CAST(CAST(CRYPT_GEN_RANDOM(2) AS INTEGER) AS FLOAT)/65535 

pero yo estoy haciendo algunos efectos extraños.

Por ejemplo:

WITH Numbers (num) 
    AS 
    (
     SELECT num 
     FROM (
       VALUES (1), (2), (3), (4), 
        (5), (6), (7), (8), 
        (9), (10) 
      ) AS Numbers (num) 
    ), 
    RandomNumber (num) 
    AS 
    (
     SELECT CAST(
        (CAST(CAST(CRYPT_GEN_RANDOM(2) AS INTEGER) AS FLOAT)/65535) 
        * (SELECT COUNT(*) FROM Numbers) + 1 
        AS INTEGER 
       ) 
    ) 
SELECT T1.num, R1.num 
    FROM Numbers AS T1 
     INNER JOIN RandomNumber AS R1 
      ON T1.num = R1.num; 

yo esperaría que esta para volver exactamente una fila con los dos valores de las columnas iguales.

Sin embargo, devuelve cero, una o más filas, con valores de columna que solo ocasionalmente son iguales.

¿Alguna idea de lo que está pasando aquí?

+0

¡Cambie el nombre como el gato de Schrödinger o el Principio de Incertidumbre en el Servidor SQL! hahah –

+0

[Blogged acerca de esto aquí] (http://sqlperformance.com/2014/06/t-sql-queries/dirty-secrets-of-the-case-expression). –

Respuesta

8

Prueba esto:

select abs(checksum(newid()))%200 

actualización

Algo raro está pasando aquí:

select 'Not in the range! This is impossible!' [Message] 
where cast(CAST(CAST(CRYPT_GEN_RANDOM(2) AS int) AS float)/65535 * 10 as int) 
not in (0,1,2,3,4,5,6,7,8,9) 

Hit F5 hasta que llegue el mensaje.

Actualización 2

Esta consulta tiene el mismo efecto:

select 'Not in the range! This is impossible!' [Message] 
where abs(checksum(newid()))%10 
not in (0,1,2,3,4,5,6,7,8,9) 

Actualización 3

select N'WTF? Schrödinger''s cat!' [Message], * 
from (select 0 union select 1) t(n) 
join (select abs(checksum(newid()))%2 rnd) r(n) on t.n = r.n 

Y esta última consulta a veces puede volver 2 filas que significa esencialmente que abs(checksum(newid()))%2 devuelve 0 y 1 al mismo tiempo que es impossi como se incluye en la declaración "seleccionar solo una fila", el valor se actualiza más adelante después de que se haya realizado la unión. : | Y luego, la unión ocurre de nuevo, lo cual es desconcertante.

Actualización 4

Es a known bug en Microsoft Connect. Y aquí está an insightful article sobre lo que está sucediendo.

+0

Gracias por la alternativa, estoy seguro de que hay más. ¿Pero puedes explicar los extraños efectos de * my * code? – onedaywhen

+0

Quizás el OP tenga una buena razón para necesitar un número aleatorio de calidad criptográfica. – LukeH

+0

@onedaywhen @LukeH Veo ... –