2017-07-27 81 views
-1

最近發現了一些東西(可以肯定,我的錯是因爲沒有閱讀文檔),這使我對SQLServer的DATEDIFF函數感到震驚;它計算兩個指定日期之間的區間邊界數。SQLServer的分數DATEDIFF?

這意味着我可以問它的天01 Jan 23:5701 Jan 23:59之間的數字,它會返回0,但如果我問01 Jan 23:5902 Jan 00:01之間的天它會告訴我他們之間有1天。時間跨度相同:2分鐘,但突然一個是0天的差異,一個是1天的差異

來自Oracle和.Net背景我可以看到我在假設TSQL中的DATEDIFF工作方式相同(即準備一個時間段,然後將其四捨五入到指定的時間間隔),但還有什麼選擇?

如果我想精確找出小數點後兩位日期之間有多少年,我該如何在SQLServer中執行此操作?我不希望1月1日至12月31日的結果返回0年,但是2000年12月31日至2002年1月01日返回2年,因爲這些都是嚴重錯誤,並且距離0.997和1.005(不是確切的計算),它們應該更多很可能是..

答案顯然不是DATEDIFF的日子和365.0的差別,不僅因爲datediff即使對於DAYS(按照我的2分鐘示例)通常是「錯誤的」,也是因爲沒有一年365天。相同的幾個月 - >他們並不總是指定的時間間隔長,所以用天數除以31(或30,29或28)是沒有意義的。出於同樣的原因,我不能做簡單的事情(endDateTime - startDateTime)/x數學

+0

難道你看這個問題的答案[鏈接](https://stackoverflow.com/questions/23145404/calculate-exact-date-difference-in-years-using-sql)?有一些方法。 – Rokuto

+1

「但也因爲一年365天不總是」。 2017-03-29和2017-03-30之間的(小數)年數大於2000-03-29和2000-03-30之間在模型中的差異,因爲後者是閏年,並且是從而稍微長一點?您是否真的想把所有歷年的準確長度考慮在內?因爲這不是一個漂亮的計算。大多數人只需要365.25天的Julian年就可以完成。 –

+1

就.NET背景而言 - 兩個日期之間的區別是TimeSpan,並且沒有TotalYears屬性。目前還不清楚你打算如何獲得0.997和1.005的值。 –

回答

0

如果你想要的準確性,你可以去做datediff分鐘,並相應地乘以結果。你可以調整@dateFrom@dateTo與下面的代碼來測試輸出:

DECLARE @dateFrom DATETIME, @dateTo DATETIME 

SET @dateFrom = '2017-07-01 23:59' 
SET @dateTo = '2017-07-02 00:01' 

SELECT DATEDIFF(MINUTE, @dateFrom, @dateTo) minsDiff 

SELECT DATEDIFF(MINUTE, @dateFrom, @dateTo)/60.0 hoursDiff 

SELECT DATEDIFF(MINUTE, @dateFrom, @dateTo)/60.0/24.0 daysDiff 

SELECT DATEDIFF(MINUTE, @dateFrom, @dateTo)/60.0/24.0/365.25 yearsDiff 

SELECT DATEDIFF(MINUTE, @dateFrom, @dateTo)/60.0/24.0/365.25 * 12 monthsDiff 

這一切都取決於你要舉報什麼,什麼你的業務邏輯。你可以像這樣其他查詢:

-- to track a change in days - take off the time portion: 
SELECT DATEDIFF(DAY, CAST(@dateFrom AS DATE), CAST(@dateTo AS DATE)) daysDiff 
-- to track a change in years - you use the year funtion: 
SELECT YEAR(@dateTo) - YEAR(@dateFrom) yearsDiff 
+0

我不確定這些問題中的任何一個能夠回答這個問題,因爲這是問題後面段落中引用的「我不想要的」的一個例子。 'Year(a) - Year(b)'也爲我的'dec 2000 to jan 2002'例子報告2,儘管它只有1.005年 –

+2

@CaiusJard儘管這可以歸結爲您的業務邏輯,但我只是想說明有一些方法可以根據您希望應用程序顯示的內容來獲得所需的輸出。關於你的一年查詢,從上面發佈的這個會給你這個值:'SELECT DATEDIFF(MINUTE,@dateFrom,@dateTo)/ 60.0/24.0/365.25 yearsDiff' – Tanner

1

UPDATE:這個代碼不包括DST。

您也可以建立自己的代碼,它將計算日期之間的差異並將其放入函數中。

DECLARE @dateFrom DATETIME, @dateTo DATETIME 

SET @dateFrom = '2000-12-31 23:59' 
SET @dateTo = '2002-01-02 00:01' 


SELECT DATEDIFF(YEAR, DATEADD(year,DATEDIFF(year,0,DATEADD(year,1,@dateFrom)),0), DATEADD(year,DATEDIFF(year,0,@dateTo),0)) 
     + CASE WHEN YEAR(@dateFrom) < YEAR(@dateTo) THEN (DATEDIFF(MINUTE, @dateFrom, CAST(YEAR(@dateFrom) AS CHAR(4))+'-12-31 23:59') + 1)/(1.0*DATEDIFF(minute, CAST(YEAR(@dateFrom) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateFrom) AS CHAR(4))+'-12-31 23:59') + 1) 
     + (DATEDIFF(MINUTE, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00',@dateTo) + 1)/(1.0*DATEDIFF(minute, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateTo) AS CHAR(4))+'-12-31 23:59') + 1) 
     ELSE (DATEDIFF(MINUTE,@dateFrom, @dateTo) + 1)/(1.0*DATEDIFF(minute, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateTo) AS CHAR(4))+'-12-31 23:59') + 1) END 
--Result: 1.002745428591627 

此代碼需要的意見,所以:

+1需要獲得日期之間的分鐘確切數字。

這是用來計算一年有多少分鐘。

(1.0*DATEDIFF(minute, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateTo) AS CHAR(4))+'-12-31 23:59') + 1) 

這給了我們今年的開始。

DATEADD(year,DATEDIFF(year,0,@dateTo),0) 

這一段代碼計算@dateFrom@dateTo之間的全年。

DATEDIFF(YEAR, DATEADD(year,DATEDIFF(year,0,DATEADD(year,1,@dateFrom)),0), DATEADD(year,DATEDIFF(year,0,@dateTo),0)) 

這是計算「偏」年。我們正在計算還剩多少分鐘到年底。

(DATEDIFF(MINUTE, @dateFrom, CAST(YEAR(@dateFrom) AS CHAR(4))+'-12-31 23:59') + 1)/(1.0*DATEDIFF(minute, CAST(YEAR(@dateFrom) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateFrom) AS CHAR(4))+'-12-31 23:59') + 1) 

與我們以上所述相似,但是對於@dateTo也有類似之處。

(DATEDIFF(MINUTE, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00',@dateTo) + 1)/(1.0*DATEDIFF(minute, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateTo) AS CHAR(4))+'-12-31 23:59') + 1) 

在這裏,我們計算年的時候@dateFrom@dateTo具有相同的年份部分。

(DATEDIFF(MINUTE,@dateFrom, @dateTo) + 1)/(1.0*DATEDIFF(minute, CAST(YEAR(@dateTo) AS CHAR(4))+'-01-01 00:00', CAST(YEAR(@dateTo) AS CHAR(4))+'-12-31 23:59') + 1) 
+1

想要聽聽什麼意思? 「DST呢?」 –

+0

@JeroenMostert哈,我沒有想過。我用這個代碼來計算,在那裏我不必關心DST,因爲我們沒有使用時間部分。需要考慮它。不管怎樣,謝謝。 – Rokuto

+1

我並不是認真的建議重寫它以考慮DST,因爲即使可以完成它,也會有不合理的困難。我知道很少有項目需要在當地時間之間有確切的分鐘數。在你做的地方,你可能不想把這個計算回分數年,因爲它會有什麼好處?如果你想添加或比較句點,你可以/應該使用你正在處理的最小有意義的單位(以分鐘或秒爲單位),以UTC表示。 –