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的元问题。