转换SQL server datetime字段以仅比较日期部分,并使用索引查找

时间:2008-12-09 14:59:53

标签: sql-server-2005 datetime

我一直在每个日期字段上执行convert(varchar,datefield,112)我在SQL服务器中的'之间'查询中使用,以确保我只根据时间部分计算日期而不丢失任何日期日期时间字段。

现在,我听说转换器不可索引,并且在SQL Server 2005中有更好的方法来比较查询中日期时间的日期部分,以确定日期是否属于某个范围。

这样做的最佳,可索引的方法是什么:

select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'

5 个答案:

答案 0 :(得分:66)

剥离日期时间字段的时间部分的最佳方法是使用datediff和dateadd函数。

   DateAdd(day, datediff(day,0, MydateValue), 0)

这有利于SQL Server将日期存储为两个整数,一个表示自“0”日起的天数 - (1月1900),第二个表示 滴答 (每个刻度约为3.33毫秒)从午夜(当时)*。

上面的公式只需要读取第一个整数。不需要转换或处理,因此速度非常快。

要使查询使用索引...首先在输入过滤参数上使用此公式,或在表日期时间字段的等号的“其他”侧使用此公式,以便查询优化器不必对表中的每个datetime字段运行计算,以确定哪些行满足过滤谓词。这使您的搜索参数“SARG-able”(搜索ARGument)

Where MyDateTimeColumn > DateAdd(day, 
      datediff(day,0, @MydateParameter), 0)    -- SARG-able

而不是

Where DateAdd(day, datediff(day,0, 
      MyDateTimeColumn ), 0) > @MydateParameter -- Not SARG-able

*注意。在内部,第二个整数(时间部分)存储刻度。在一天中有24 x 60 X 60 X 300 = 25,920,000个刻度(偶然地在最大值之下,32位整数可以保持)。但是,在算术修改日期时间时,您无需担心这一点...当从日期时间添加或减去值时,您可以将该值视为分数,就好像它恰好等于一天的小数部分一样,就像完整日期时间值是一个浮点数,由表示日期的整数部分和表示时间的小数部分组成。即,

`Declare @Dt DateTime  Set @Dt = getdate()  
 Set @Dt = @Dt + 1.0/24  -- Adds one hour  
 Select @Dt  
 Set @Dt = @Dt - .25 -- Moves back 6 hours  
 Select @Dt`

答案 1 :(得分:5)

将数字类型转换为字符串值(一种拳击类型)并不是执行所需操作的最佳方法。它实际上不是关于索引的,因为实际的列类型是日期时间。

如果您正在寻找日期的最佳查询方式,那么您的示例是正确的,但您可能需要考虑MSSQL中3 ms的精度差异。这可能意味着一天的记录可以显示在另一天的结果中。

这个

select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'

应该是这个

select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<='08-14-2008 23:59:59.996'

答案 2 :(得分:2)

这是正确的 - 进行转换将为查询的每一行执行转换。最好将日期列保留为日期,并将where子句作为日期传递:

select * from appointments where appointmentdate between 
'08/01/2008' AND '08/16/2008'

注意:离开时间是指午夜(00:00.000),因此您将包括08/01的所有时间,以及08/15的所有时间,以及08/16/2008 00:00的所有时间: 00

答案 3 :(得分:1)

让计算的持久列计算您需要的表达式。如果计算并保留列,则也可以将它们编入索引。

答案 4 :(得分:0)

还有http://www.stillnetstudios.com/comparing-dates-without-times-in-sql-server/

中描述的方式
SELECT CAST(FLOOR(CAST( getdate() AS float )) AS datetime)