CRYPT_GEN_RANDOM странные эффекты - PullRequest
5 голосов
/ 22 сентября 2010

Я хочу случайным образом выбрать значение из небольшого диапазона целых чисел (менее 200). Как альтернатива

SELECT RAND()

Я пытаюсь использовать

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

но я получаю некоторые странные эффекты.

Например:

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;

Я ожидаю, что это вернет ровно одну строку с равными значениями обоих столбцов.

Однако он возвращает ноль, одну или несколько строк, причем значения столбцов равны лишь иногда.

Есть идеи, что здесь происходит?

1 Ответ

8 голосов
/ 22 сентября 2010

Попробуйте это:

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

Обновление

Здесь происходит что-то подозрительное:

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)

Нажимайте F5, пока не получите сообщение.

Обновление 2

Этот запрос имеет тот же эффект:

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)

Обновление 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

И этот последний запрос может иногда возвращать 2 строки, что, по сути, означает, что abs(checksum(newid()))%2 возвращает 0 и 1 одновременно, что невозможно, поскольку оно включено в оператор «выбрать только одну строку», следовательно, значение обновляется позже после соединение было сделано. : | И тогда соединение происходит снова, что ошеломляет.

Обновление 4

Это известная ошибка в Microsoft Connect. И вот проницательная статья о том, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...