我一直在每个日期字段上执行convert(varchar,datefield,112)
我在SQL服务器中的'之间'查询中使用,以确保我只根据时间部分计算日期而不丢失任何日期日期时间字段。
现在,我听说转换器不可索引,并且在SQL Server 2005中有更好的方法来比较查询中日期时间的日期部分,以确定日期是否属于某个范围。
这样做的最佳,可索引的方法是什么:
select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
答案 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)