2010-04-14 140 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

相關問題