SQLServer的小数DATEDIFF?

时间:2017-07-27 09:53:16

标签: sql-server tsql datediff

最近发现了一些东西(当然,我的错误是没有阅读文档),这让我对SQLServer的DATEDIFF功能感到震惊;它计算两个指定日期之间的间隔边界数。

这意味着我可以询问01 Jan 23:5701 Jan 23:59之间的天数,它会返回0,但如果我要求01 Jan 23:59和{{1}之间的天数它会告诉我他们之间有一天。时间跨度相同:2分钟,但突然一个是0天的差异,一个是1天的差异

来自Oracle和.Net背景我可以看到我假设TSQL中的DATEDIFF等效地工作(即准备一个时间跨度然后将其四舍五入到指定的时间间隔),我犯了一个严重的错误,但是替代方案是什么?

如果我想准确地找出小数位,两个日期之间有多少年,我该如何在SQLServer中完成?我不希望从1月1日到12月31日的结果返回0年,但是2000年12月31日到2002年1月1日返回2年,因为这些是严重错误并且距离0.997和1.005(不是确切的计算)它们应该更多可能是......

答案显然不是DATEDIFF的天数除以365.0,不仅因为dateiff通常是“错误的”,即使是DAYS(根据我的2分钟例子),也因为并非总是365天年。几个月相同 - >它们并不总是指定的间隔长度,因此将天数除以31(或30,29或28)是没有意义的。出于同样的原因,我不能做简单的02 Jan 00:01数学

2 个答案:

答案 0 :(得分:1)

更新:此代码不包含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 :(得分: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