Выберите случайную дату в пределах определенного диапазона - PullRequest
10 голосов
/ 02 апреля 2011

Как выбрать случайную дату в определенном включающем диапазоне, скажем, «1950-01-01» и «1999-12-31» с SQL Server?

Ответы [ 2 ]

15 голосов
/ 02 апреля 2011
select DateAdd(d, ROUND(DateDiff(d, '1950-01-01', '1999-12-31') * RAND(), 0), '1950-01-01')

РЕДАКТИРОВАТЬ

Если это должно быть выполнено как часть инструкции, которая возвращает несколько строк, или как часть обновления, RAND () вернет одно значение дляВесь набор результатов.Для этого случая можно использовать RAND (CHECKSUM (NEWID ())).

select DateAdd(d, ROUND(DateDiff(d, '1950-01-01', '1999-12-31') * RAND(), 0), '1950-01-01'),
       DateAdd(d, ROUND(DateDiff(d, '1950-01-01', '1999-12-31') * RAND(CHECKSUM(NEWID())), 0), '1950-01-01')
from master..spt_values where type = 'P'
12 голосов
/ 02 апреля 2011

Это даст вам 1000 строк данных для вставки.

DECLARE @D1 DATE = '19500101'
DECLARE @D2 DATE = '19991231'

   ;WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
        E02(N) AS (SELECT 1 FROM E00 a, E00 b),
        E04(N) AS (SELECT 1 FROM E02 a, E02 b),
        E08(N) AS (SELECT 1 FROM E04 a, E04 b),
        E16(N) AS (SELECT 1 FROM E08 a, E08 b),
        E32(N) AS (SELECT 1 FROM E16 a, E16 b),
   cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
   SELECT TOP 1000
    DATEADD(DAY,ABS(CHECKSUM(NEWID())) % (1+DATEDIFF(DAY,@D1,@D2)),@D1)
   FROM  cteTally

Примечание: этот ответ первоначально использовал ABS(CAST(CRYPT_GEN_RANDOM(4) AS INT)) для генерации случайных чисел.В отличие от RAND(), который оценивается только один раз для каждого оператора, он оценивается один раз для каждой строки, поэтому будет работать.

Однако кажется, что Оптимизатор запросов не осознает этого и рассматривает его как константу.Для генерации случайных данных это, вероятно, не будет иметь значения (если вы не заполняете столбец, ограниченный внешним ключом)

, но я только что протестировал альтернативу ABS(CHECKSUM(NEWID())), чтобы увидеть, было ли какое-либо преимущество в производительностиодин за другим.

Типичная скорость генерации 1 000 000 строк с использованием таблицы чисел, приведенной выше, и выбор значения MAX (чтобы избежать затрат на возврат всех этих строк клиенту)

ABS(CAST(CRYPT_GEN_RANDOM(4) AS INT))
/*CPU time = 4180 ms,  elapsed time = 4395 ms.*/

ABS(CHECKSUM(NEWID()))
/*CPU time = 953 ms,  elapsed time = 1163 ms.*/

(SELECT 1) /*A constant value just to get a baseline*/
/*CPU time = 499 ms,  elapsed time = 457 ms.*/

Так что, если вам не нужен криптографически безопасный PRNG, его, вероятно, лучше избегать!

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