Псевдослучайная последовательность в MSSQL

Использование встроенной функции rand() в запросах чревато проблемой получения последовательности одинаковых чисел. Например

CREATE TABLE T1 (id int);
GO

INSERT INTO T1
SELECT 1
UNION
SELECT 2
UNION
SELECT 3;

SELECT rand(), id FROM T1;

Выдает одинаковые значения

rand_value             id
---------------------- -----------
0,581556027773794      1
0,581556027773794      2
0,581556027773794      3

(3 row(s) affected)

Конечно, можно написать свою функцию - аналог rand(), используя один из алгоритмов генерации псевдослучайно последовательности. Но попробуем справиться встроенными средствами.

Если подавать на вход rand() в качестве параметра "seed" (инициализатора) псевдослучайные целые числа, то и на выходе мы получим псевдослучайную последовательность в диапазоне (0, 1). В качестве поставщика чисел для seed подойдет генератор GUID - функция newid(). Например так:

rand(abs(convert(int, convert(varbinary, newid()))))

Обернуть rand() в пользовательскую скалярную функцию нельзя согласно ограничениям MS SQL Server. Воспользуемся проекцией (view).

CREATE VIEW rand2 AS 
  SELECT rand(abs(convert(int, convert(varbinary, newid())))) AS rand_value;

Использовать проекцию в запросах можно так:
SELECT rand2.rand_value, id FROM T1 CROSS JOIN rand2;

или так:
SELECT (SELECT rand_value FROM rand2) AS rand_value, id FROM T1;

Повторив тест, получаем

rand_value             id
---------------------- -----------
0,349013124792225      1
0,780734712117597      2
0,488939877887713      3

(3 row(s) affected

За рамками заметки остается вопрос длины псевдослучайной последовательности. Оставляю этот вопрос читателю.

Ответить

Содержание этого поля является приватным и не предназначено к показу.
  • Allowed HTML tags: <a> <em> <strong> <b> <i> <strike> <center> <del> <cite> <code> <pre> <ul> <ol> <li> <dl> <dt> <dd> <p> <br> <h1> <h2> <h3> <h4> <img> <hr> <sup> <sub> <blockquote>
  • Use <!--pagebreak--> to create page breaks.
  • You can enable syntax highlighting of source code with the following tags: <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • Строки и параграфы переносятся автоматически.

Подробнее о форматировании

Captcha
Вопрос для предотвращения спама
Copy the characters (respecting upper/lower case) from the image.