2012-07-08 105 views

回答

9

假设

首先,假设你有一个包含数据库表中包含开始日期时间列和结束日期时间列,它们一起定义日期时间范围E:

CREATE DATABASE StackOverflow11387226; 
GO 

USE StackOverflow11387226; 
GO 

CREATE TABLE DateTimeRanges (
    StartDateTime DATETIME NOT NULL, 
    EndDateTime DATETIME NOT NULL 
); 
GO 

ALTER TABLE DateTimeRanges 
ADD CONSTRAINT CK_PositiveRange CHECK (EndDateTime > StartDateTime); 

,并假定表包含一些数据:

INSERT INTO DateTimeRanges (
    StartDateTime, 
    EndDateTime 
) 
VALUES 
    ('2012-07-09 00:30', '2012-07-09 01:30'), 
    ('2012-01-01 00:00', '2013-01-01 00:00'), 
    ('1988-07-25 22:30', '2012-07-09 00:30'); 
GO 

方法

以下SELECT语句返回开始日期时间,结束日期时间,并与分精度的伪随机日期时间大于或等于开始日期时间并小于第二个日期时间:

SELECT 
    StartDateTime, 
    EndDateTime, 
    DATEADD(
    MINUTE, 
    ABS(CHECKSUM(NEWID())) % DATEDIFF(MINUTE, StartDateTime, EndDateTime) + DATEDIFF(MINUTE, 0, StartDateTime), 
    0 
) AS RandomDateTime 
FROM DateTimeRanges; 

结果

因为NEWID()函数是非确定性的,所以这将为每次执行返回不同的结果集。这是我刚才生成的结果集:

StartDateTime   EndDateTime    RandomDateTime 
----------------------- ----------------------- ----------------------- 
2012-07-09 00:30:00.000 2012-07-09 01:30:00.000 2012-07-09 00:44:00.000 
2012-01-01 00:00:00.000 2013-01-01 00:00:00.000 2012-09-08 20:41:00.000 
1988-07-25 22:30:00.000 2012-07-09 00:30:00.000 1996-01-05 23:48:00.000 

所有在列的startDateTime和EndDateTime值之间的列RandomDateTime谎言值。

说明

这种产生随机值的技术是由于Jeff Moden引起的。他上的SQL Server中央写了great article有关数据生成。阅读它以获得更全面的解释。需要注册,但它非常值得。

的想法是生成一个随机从一开始日期时间偏移,并添加偏移量开始日期时间的开始日期时间和结束日期时间之间获得一个新的日期时间。

表达DATEDIFF(MINUTE, StartDateTime, EndDateTime)表示开始日期时间和结束日期时间之间的分钟总数。偏移量必须小于或等于此值。

表达ABS(CHECKSUM(NEWID()))产生用于每一行的独立随机正整数。该表达式可以具有从0到2,147,483,647的任何值。这个表达式第一个表达式给出了一个有效的偏移量,以分钟为单位

epxression DATEDIFF(MINUTE, 0, StartDateTime)表示开始日期时间和参考日期时间之间的总分钟数0,这是'1900-01-01 00:00:00.000'的简写。引用日期时间的值并不重要,但重要的是在整个表达式中使用相同的引用日期。将其添加到偏移量以获取参考日期时间之间的总分钟数。

通过将前一个表达式生成的分钟数添加到引用日期时间,生态封装DATEADD函数将其转换为日期时间值。

+0

非常好地完成和代码的伟大的总结。并感谢荣誉提及。对此,我真的非常感激。 – 2012-10-10 03:25:04

+0

@JeffModen没问题。感谢您发布您的方法! – 2012-10-10 08:58:40

8

您可以使用RAND此:

select cast(cast(RAND()*100000 as int) as datetime) 

here

SQL的小提琴看起来相当不错:http://sqlfiddle.com/#!3/b9e44/2/0

+0

嗨时间,对不起,我忘了提及它需要在2日期之间 – 2012-07-08 22:58:50

+1

@Developer:[链接](http://www.sqlservercentral.com/Forums/Topic499265-8-1.aspx#bm501386)我我们提供了一个方法来指定一个范围(找到乘数:'Select cast(cast('1 Jan 2010'as datetime)as int)')。 – 2012-07-09 07:25:01