如果我有一個日期值,如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