MS SQLdate只有没有时间

大家好,

我已经有一段时间困惑了很长一段时间,基本上使用T-SQL来实现DateTime SQLtypes。 本质上,我想要采取2008-12-1 14:30:12的date时间值,并使其2008-12-1 00:00:00。 我们为报告运行的查询中有很多在WHERE子句中使用了一个date值,但是我有一天的开始和结束date值,并使用BETWEEN,或者我find了其他方法。

目前我使用以下: WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

不过,这似乎有点笨重。 我希望能有像CAST([tstamp] AS DATE)这样更简单的东西,

有些地方在线推荐使用DATEPART()函数,但是最后我得到了这样的结果:

WHERE DATEPART(year, [tstamp]) = DATEPART(year, @dateParam) AND DATEPART(month, [tstamp]) = DATEPART(month, @dateParam) AND DATEPART(day, [tstamp]) = DATEPART(day, @dateParam)
WHERE DATEPART(year, [tstamp]) = DATEPART(year, @dateParam) AND DATEPART(month, [tstamp]) = DATEPART(month, @dateParam) AND DATEPART(day, [tstamp]) = DATEPART(day, @dateParam) 

也许我太在意小事了,如果是的话,请让我知道。 我只是想确保我写的东西尽可能高效。 我想消除任何薄弱环节。

有什么build议么?

谢谢,
C

谢谢大家的好评。 很多有用的信息。 我将要改变我们的function,以消除操作员左侧的function。 虽然我们的大多数date列不使用索引,但它可能仍然是一个更好的做法。

这是非常糟糕的性能,看看只有在一个数据库你可以得到1000%+改善通过改变几行代码

操作员左侧的function不好

这是你需要做的

 declare @d datetime select @d = '2008-12-1 14:30:12' where tstamp >= dateadd(dd, datediff(dd, 0, @d)+0, 0) and tstamp < dateadd(dd, datediff(dd, 0, @d)+1, 0) 

运行这个来看看它做了什么

 select dateadd(dd, datediff(dd, 0, getdate())+1, 0) select dateadd(dd, datediff(dd, 0, getdate())+0, 0) 

如果您正在使用SQL Server 2008,现在已经内置了这个function,请在网上参阅书籍

CAST(GETDATE() AS date)

其他人发布的date函数是处理这个问题的最正确的方法。

然而,你提到“floor”这个词是很有趣的,因为这里有一点点黑客会跑得更快:

 CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime) 

CONVERT(date, GETDATE())CONVERT(time, GETDATE())在SQL Server 2008中工作。我不确定2005年。

这个怎么样?

 SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0) 

是的,T-SQL有时候会觉得非常原始,而这些东西往往会促使我用自己select的语言(如C#)来做很多我的逻辑。

然而,当你出于性能的原因绝对需要在SQL中做这些事情时,最好的办法是创build函数来容纳这些“algorithm”。

看看这篇文章。 他提供了很多方便的SQL函数,我认为这些函数可以帮助你。

http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx

仔细一点,如果使用WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam东西,它将强制对表进行扫描,并且没有索引将用于该部分。

更简洁的方法是定义一个计算列

 create table #t ( d datetime, d2 as cast (datepart(year,d) as varchar(4)) + '-' + right('0' + cast (datepart(month,d) as varchar(2)),2) + '-' + right('0' + cast (datepart(day,d) as varchar(2)),2) ) -- notice a lot of care need to be taken to ensure the format is comparable. (zero padding) insert #t values (getdate()) create index idx on #t(d2) select d2, count(d2) from #t where d2 between '2008-01-01' and '2009-01-22' group by d2 -- index seek is used 

这样,您可以直接检查d2列,并使用索引,而不必在转换过程中搞清楚。

 DATEADD(d, 0, DATEDIFF(d, 0, [tstamp])) 

编辑:虽然这将删除您的date时间的一部分,它也将使条件不可SARGable 。 如果这对于这个查询来说很重要,那么索引视图或者一个between子句是比较合适的。

或者你可以使用

 declare @d datetimeselect @d = '2008-12-1 14:30:12' where tstamp BETWEEN dateadd(dd, datediff(dd, 0, @d)+0, 0) AND dateadd(dd, datediff(dd, 0, @d)+1, 0) 

这是一个查询,将返回在一定范围内的所有结果。

 DECLARE @startDate DATETIME DECLARE @endDate DATETIME SET @startDate = DATEADD(day, -30, GETDATE()) SET @endDate = GETDATE() SELECT * FROM table WHERE dateColumn >= DATEADD(day, DATEDIFF(day, 0, @startDate), 0) AND dateColumn < DATEADD(day, 1, DATEDIFF(day, 0, @endDate)) 

FWIW,多年来我一直在做同样的事情

 CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam 

在我看来,这是在灵活性,速度和可读性方面剥离时间的更好方法之一。 (抱歉)。 build议的一些UDF函数可能是有用的,但UDF可能会较慢,更大的结果集。

 WHERE DATEDIFF(day, tstamp, @dateParam) = 0 

如果你不在乎时间,这应该让你在那里。

这是为了回答在不关心时间的情况下比较两个值的date的元问题。