只有没有时间的MS SQL日期

时间:2009-01-21 21:30:51

标签: sql sql-server tsql

问题

大家好,

我在很长一段时间内遇到了一些困惑,主要是使用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

解决方案

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

12 个答案:

答案 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

如果你不关心时间,这应该可以帮助你。

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