大家好,
我在很长一段时间内遇到了一些困惑,主要是使用T-SQL对DateTime SQL类型进行了修改。基本上,我想将DateTime值设为2008-12-1 14:30:12并将其设为2008-12-1 00:00:00。我们为报告运行的很多查询在WHERE子句中使用了一个日期值,但是我有一天的开始和结束日期值并使用BETWEEN,或者我找到了其他一些方法。
目前我正在使用以下内容:
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)
也许我过分关注小事,如果是,请告诉我。我只是想确保我写的东西尽可能高效。我想消除任何薄弱环节。
有什么建议吗?
谢谢,
C
感谢大家的好评。很多有用的信息。我将改变我们的功能以消除操作员左侧的功能。虽然我们的大多数日期列都不使用索引,但它可能仍然是一种更好的做法。
答案 0 :(得分:79)
如果你正在使用SQL Server 2008,它现在已内置,请参阅books online
CAST(GETDATE() AS date)
答案 1 :(得分:35)
这对性能非常不利,请查看Only In A Database Can You Get 1000% + Improvement By Changing A Few Lines Of Code
操作员左侧的功能不好
这是你需要做的事情
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)
答案 2 :(得分:9)
其他人发布的日期函数是处理此问题的最正确方法。
然而,你提到“地板”一词很有趣,因为有一点点黑客会运行得更快:
CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime)
答案 3 :(得分:7)
CONVERT(date, GETDATE())
和CONVERT(time, GETDATE())
适用于SQL Server 2008.我不确定2005年。
答案 4 :(得分:5)
这个怎么样?
SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0)
答案 5 :(得分:1)
DATEADD(d, 0, DATEDIFF(d, 0, [tstamp]))
编辑:虽然这会删除日期时间的时间部分,但它也会使条件为non SARGable。如果这对于此查询很重要,则索引视图或between子句更合适。
答案 6 :(得分:1)
是的,T-SQL有时会感觉非常原始,而且这些事情经常会让我用我选择的语言(例如C#)做很多逻辑。
但是,出于性能原因,当您绝对需要在SQL中执行某些操作时,最好的办法是创建函数来存放这些“算法”。
看看这篇文章。他提供了很多方便的SQL函数,我认为这些函数可以帮助你。
http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx
答案 7 :(得分:1)
在这里小心,如果你使用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列,并且将使用索引,您无需进行转换。
答案 8 :(得分: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))
答案 9 :(得分:0)
FWIW,我多年来一直和你做同样的事情
CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam
在我看来,这是在灵活性,速度和可读性方面剥离时间的更好方法之一。 (抱歉)。某些建议的UDF函数可能很有用,但UDF可能会因较大的结果集而变慢。
答案 10 :(得分:0)
或者你可以使用
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)
答案 11 :(得分:-1)
WHERE DATEDIFF(day, tstamp, @dateParam) = 0
如果你不关心时间,这应该可以帮助你。
这是为了回答在不关心时间的情况下比较两个值的日期的元问题。