2011-04-01 71 views
10

如何在特定的包含範圍內選擇隨機日期,比方說SQL Server的'1950-01-01'和'1999-12-31'?在特定範圍內選擇一個隨機日期

+0

您是否試圖在同一時間爲多行生成數據,或者只是一個日期?我只是想知道你是否試圖建立一些測試數據插入到表中。 – Jeff 2011-04-01 22:34:39

+0

嗨,傑夫。我需要一個範圍內的隨機日期,以便運行一個循環,並隨機生成一個測試表。 :) – 2011-04-01 22:37:06

+0

你需要多少行數據? – 2011-04-01 22:39:19

回答

12

這會給你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它可能最好避免!

+0

嗨馬丁。非常感謝你。看起來,如果我想甚至'1992-12-31',我必須將@ d2聲明爲'2000-01-01',否則查詢不包含最後一天。 – 2011-04-01 22:40:04

+0

@nick - 我已將其更改爲「1 + DATEDIFF(DAY,@ D1,@ D2)」以解決該問題。 – 2011-04-01 22:43:25

+0

你簡直太棒了:)謝謝你一直奉獻我的時間。對此,我真的非常感激。再次感謝馬丁。 – 2011-04-01 22:45:06

15
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' 
+0

這似乎是隨機選擇1/1/1950或12/31/1999,但不是在兩者之間的任何日期。 – JustinStolle 2011-04-01 22:36:25

+0

嗨。感謝您的回覆。我試過了你的查詢,但它總是返回已經寫入的那兩個值中的一個。 – 2011-04-01 22:41:21

+0

+1現在效果很好。謝謝;) – 2011-04-02 00:00:47

相關問題