如果我有一个日期值,如2010-03-01 17:34:12.018
在SQL Server中截断日期的最佳方法是什么?
什么是最有效的方法来把它变成2010-03-01 00:00:00.000
?
作为第二个问题,模拟Oracle的TRUNC
函数的最佳方法是什么?它将允许您在Year,Quarter,Month,Week,Day,Hour,Minute和Second边界截断?
如果我有一个日期值,如2010-03-01 17:34:12.018
在SQL Server中截断日期的最佳方法是什么?
什么是最有效的方法来把它变成2010-03-01 00:00:00.000
?
作为第二个问题,模拟Oracle的TRUNC
函数的最佳方法是什么?它将允许您在Year,Quarter,Month,Week,Day,Hour,Minute和Second边界截断?
要四舍五入到最近的整天,有三种方法可以广泛使用。第一个使用datediff
查找自0
datetime以来的天数。日期时间0
对应于1900年1月1日。通过将日期差异添加到开始日期,您可以四舍五入到一整天;
select dateadd(d, 0, datediff(d, 0, getdate()))
第二种方法是基于文本:它截断与varchar(10)
的文字说明,只留下日期部分:
select convert(varchar(10),getdate(),111)
第三种方法使用的事实datetime
是真正代表一个浮点自1900年以来的天数。因此,通过舍入到整数,例如使用floor
,即可获得当天的开始时间:
select cast(floor(cast(getdate() as float)) as datetime)
要回答你的第二个问题,本周开始是棘手的。一种方法是减去一天的星期几:
select dateadd(dd, 1 - datepart(dw, getdate()), getdate())
这将返回一个部分时间太多,所以你必须将其与时间剥离方法中的一种结合,得到了第一次约会。例如,@start_of_day
作为可读性的变量:
declare @start_of_day datetime
set @start_of_day = cast(floor(cast(getdate() as float)) as datetime)
select dateadd(dd, 1 - datepart(dw, @start_of_day), @start_of_day)
年,月,小时和分钟与“差自1900年以来”仍能正常工作的启动的方法:
select dateadd(yy, datediff(yy, 0, getdate()), 0)
select dateadd(m, datediff(m, 0, getdate()), 0)
select dateadd(hh, datediff(hh, 0, getdate()), 0)
select dateadd(mi, datediff(mi, 0, getdate()), 0)
以秒为单位舍入需要不同的方法,因为从0
开始的秒数会产生溢出。周围的一个方法是使用一天的开始,而不是1900,作为参考日期:
declare @start_of_day datetime
set @start_of_day = cast(floor(cast(getdate() as float)) as datetime)
select dateadd(s, datediff(s, @start_of_day, getdate()), @start_of_day)
为了轮由5分钟,调整分钟舍入方法。取分差的商,例如使用/5*5
:
select dateadd(mi, datediff(mi,0,getdate())/5*5, 0)
这适用于宿舍和半小时为好。
哪一个将表现最好? – 2010-04-14 16:14:08
据我所知,性能差异太小,无法衡量 – Andomar 2010-04-14 16:16:09
这就是我想知道的!我在代码中使用第二个,但我很好奇是否有更快的方法来完成它。第一个是带有第三个函数调用的两个日期函数,所以至少有三个解析操作,而第二个是使用格式应用的单个字符串转换(但其中存在着问题,库中会发生什么?)。 – jcolebrand 2010-04-14 16:16:53
尝试:
SELECT DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
UPDATE:回答关于第二个问题: 多年,你可以使用我的回答一点点修改的版本:
SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)
为季:
SELECT DATEADD(qq, DATEDIFF(qq, 0, GETDATE()), 0)
等等。
我查过了,最多分钟 - 没关系。但在秒钟我有溢出消息:
两个日期时间列的差异 在运行时导致溢出。
还有一个更新:看看下面的答案相同question
如果您使用的是SQL Server 2008中,你可以使用新的Date
数据类型是这样的:
select cast(getdate() as date)
如果你仍然需要你的值为DateTime
数据类型,你可以这样做:
select cast(cast(getdate() as date) as datetime)
,应该在SQL Server的所有版本工作方法是:
select cast(floor(cast(getdate() as float)) as datetime)
我敢打赌,这是最快的,完全避免算术。 – 2010-04-14 16:22:48
这是晚了,但会产生在后所要求的精确结果。我也觉得它比使用dateadd更直观,但这是我的偏好。
declare @SomeDate datetime = '2010-03-01 17:34:12.018'
SELECT
DATEFROMPARTS(
YEAR(@SomeDate)
,MONTH(@SomeDate)
,'01'
) AS CUR_DATE_FROM_PARTS
,DATETIMEFROMPARTS(
YEAR(@SomeDate)
,MONTH(@SomeDate)
,'01' --DAY(@SomeDate)
,'00' --DATEPART(HOUR,@SomeDate)
,'00' --DATEPART(MINUTE,@SomeDate)
,'00' --DATEPART(SECOND,@SomeDate)
,'00' --DATEPART(MILLISECOND,@SomeDate)
) AS CUR_DATETIME_FROM_PARTS
,@SomeDate AS CUR_DATETIME
,YEAR(@SomeDate) AS CUR_YEAR
,MONTH(@SomeDate) AS CUR_MONTH
,DAY(@SomeDate) AS CUR_DAY
,DATEPART(HOUR,@SomeDate) AS CUR_HOUR
,DATEPART(MINUTE,@SomeDate) AS CUR_MINUTE
,DATEPART(SECOND,@SomeDate) AS CUR_SECOND
,DATEPART(MILLISECOND,@SomeDate) AS CUR_MILLISECOND
FROM Your_Table
截断日期:2010-03-01
截断的DateTime:2010-03-01 00:00:00.000
日期时间:2010-03-01 17:34:12.017
这里是一个很好的解释类似的问题:http://stackoverflow.com/questions/923295/how-to-truncate-a-datetime-in-sql-server – Alex 2010-04-14 16:21:51