views:

21

answers:

1

I want to randomly choose a value from a small range of integers (less than 200). As an alternative to

SELECT RAND()

I'm trying to use

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

but I'm getting some strange effects.

For example:

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;

I'd expect this to return exactly one row with both column values equal.

However, it returns zero, one or more rows, with the column values being only occasionally equal.

Any idea what's going on here?

+3  A: 

Try this:

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

Update

Something fishy is going on here:

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 until you get the message.

Update 2

This query has the same effect:

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)

Update 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

And this last query may sometimes return 2 rows which essentially means that abs(checksum(newid()))%2 returns 0 and 1 at the same time which is impossible as it is included in "select one row only" statement hence the value gets updated later after the join has been made. :| And then the join occurs again which is flabbergasting.

Update 4

It is a known bug at Microsoft Connect. And here's an insightful article on what is happening.

Denis Valeev
Thanks for the alternative, I'm sure there are more. But can you explain the strange effects of *my* code?
onedaywhen
Maybe the OP has a good reason for needing a crypto-quality random number.
LukeH
@onedaywhen @LukeH I see...
Denis Valeev
Something fishy indeed!
onedaywhen
MS says: "closing this bug as 'won't fix'." Disappointing but I understand their reasoning, even though "optimization [is] allowed to change a program's semantics" does sound quite alarming!
onedaywhen
Awesome "feature"! Thanks for pointing at these articles.
VladV