2010-04-14 179 views
11

如果我有一个日期值,如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边界截断?

+0

这里是一个很好的解释类似的问题:http://stackoverflow.com/questions/923295/how-to-truncate-a-datetime-in-sql-server – Alex 2010-04-14 16:21:51

回答

25

要四舍五入到最近的整天,有三种方法可以广泛使用。第一个使用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) 

这适用于宿舍和半小时为好。

+0

哪一个将表现最好? – 2010-04-14 16:14:08

+0

据我所知,性能差异太小,无法衡量 – Andomar 2010-04-14 16:16:09

+0

这就是我想知道的!我在代码中使用第二个,但我很好奇是否有更快的方法来完成它。第一个是带有第三个函数调用的两个日期函数,所以至少有三个解析操作,而第二个是使用格式应用的单个字符串转换(但其中存在着问题,库中会发生什么?)。 – jcolebrand 2010-04-14 16:16:53

2

尝试:

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

15

如果您使用的是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) 
+0

我敢打赌,这是最快的,完全避免算术。 – 2010-04-14 16:22:48

1

这是晚了,但会产生在后所要求的精确结果。我也觉得它比使用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

相关问题