我在SQLServer 2005中存储事件,事件发生的时间很重要,必须存储在日期库中。在where子句中编写日期范围检查的最快方法是什么,以确保选择当天的所有内容?
目前,当传递@DateStart和@DateEnd时,我将@DateStart设置为午夜并将@DateEnd设置为午夜之前的最后一刻,这是当天捕捉每一个可能事件的第一件事。
IF (@DateStart IS NOT NULL)
BEGIN
SET @DateStart = CAST (
( CAST (DATEPART (yyyy,@DateStart) AS NVARCHAR(4)) +'/'+
CAST (DATEPART (mm,@DateStart) AS NVARCHAR(2)) +'/'+
CAST (DATEPART (dd,@DateStart) AS NVARCHAR(2)) +' '+
'00:00:00.000'
)
AS DATETIME)
END
IF (@DateEnd IS NOT NULL)
BEGIN
SET @DateEnd = CAST (
( CAST (DATEPART (yyyy,@DateEnd) AS NVARCHAR(4)) +'/'+
CAST (DATEPART (mm,@DateEnd) AS NVARCHAR(2)) +'/'+
CAST (DATEPART (dd,@DateEnd) AS NVARCHAR(2)) +' '+
'23:59:59.997'
)
AS DATETIME
)
END
所以where子句很容易阅读:
WHERE(EventDate> = @DateStart AND EventDate< = @DateEnd)
谢谢,
答案 0 :(得分:7)
您始终可以使用WHERE EventDate BETWEEN @DateStart AND @DateEnd
答案 1 :(得分:2)
你的where子句看起来像;
WHERE DateCol >= DATEADD(dd, DATEDIFF(dd, 0, @DateStart), 0) --Midnight on the Start date
AND DateCol < DATEADD(dd, DATEDIFF(dd, 0, @DateEnd + 1), 0) --Midnight of the day after End date
并且你的所有IF语句都会处理空参数(即IF @DateEnd IS NULL,然后设置@DateEnd = @DateStart)
如果您的表很大,您可能想要在DATEADD(dd,DATEDIFF(dd,0,DateCol),0)上建立索引。
答案 2 :(得分:1)
截断日期的最快方法,前一个午夜:
DATEADD(day,DATEDIFF(day,'19010101',LastModifiedDate),'19010101')
下午六点:
DATEADD(day,DATEDIFF(day,'19010101',LastModifiedDate)+1,'19010101')
您也可以将其包装为内联UDF:
答案 3 :(得分:0)
试试这个:
WHERE DATEPART(yyyy, EventDate) = DATEPART(yyyy, getdate())
AND DATEPART(dy, EventDate) = DATEPART(dy, getdate()) --day of year
编辑解决Tom H的评论: 我对日期字段中的索引没有任何好运;对我来说总是更好的是额外的整数列来处理年份和年份的值,并将其编入索引。
答案 4 :(得分:0)
AlexK可能是最好的主意。 我唯一担心的是在谓词中使用函数的性能。
您应该考虑在表中添加名为searchdate或类似名称的列,以包含没有时间的日期。我还建议将此列编入索引,特别是如果您要对该列的数据进行大量搜索。
当您在此列上查询时,SQL中将没有任何标量函数来抢夺索引的性能。
con ...好吧,额外的存储空间,插入期间写入数据的时间(虽然这里不多)。
SQL Server 2008更好地支持仅限日期的数据类型。你也可以办理登机手续。
答案 5 :(得分:0)
我认为这个T-SQL等同于你拥有的代码:
-- set time portion of @DateStart back to midnight SET @DateStart = CONVERT(DATETIME,CONVERT(VARCHAR(10),@DateStart,20),20) -- advance time portion of @DateEnd to last instant before next midnight SET @DateEnd = CONVERT(DATETIME,CONVERT(VARCHAR(11),@DateEnd,20)+'23:59:59.997',21)
CONVERT
函数将处理NULLS,因此不需要对NULL值进行单独测试(当然,除非您正在显示的内容之外进行一些特殊处理,否则不会通过NULL值到查询谓词(即WHERE子句)。或者,您可能希望很多参数为NULL,并且您希望避免调用CONVERT的开销。
但是,我同意Tom H.的建议,并且避免弄乱减去毫秒,而是将@DateEnd设置为第二天的午夜,例如
-- advance @DateEnd to midnight of following day SET @DateEnd = DATEADD(day,1,CONVERT(DATETIME,CONVERT(VARCHAR(10),@DateEnd,20),20))
并更改谓词以执行范围测试,如下所示:
WHERE (EventDate >= @DateStart AND EventDate < @DateEnd)
你可以避免使用单独的SET语句,并将表达式直接移到查询中,但我不希望这会提高性能,并使SQL语句更难读,你肯定想保留这些注释...
WHERE(EventDate&gt; = CONVERT(DATETIME,CONVERT(VARCHAR(10),@ DateStart,20),20) 和EventDate