使用SQL计算年份的确切日期差异

时间:2014-04-17 23:59:35

标签: sql sql-server datediff

我会自动收到数据为ETL的报告。我提取并转换了一些数据,将其加载到其他地方。我需要做的一件事是DATEDIFF,但这一年需要准确(即4。6年,而不是四舍五入。

以下是我的剧本:

select *, DATEDIFF (yy, Begin_date, GETDATE()) AS 'Age in Years'
from Report_Stage;

正在舍入'Age_In_Years'列。我如何获得多年的确切日期?

6 个答案:

答案 0 :(得分:12)

所有datediff()所做的是计算到日期之间交叉的期间边界的数量。例如

datediff(yy,'31 Dec 2013','1 Jan 2014')

返回1.

如果计算两个日期之间的差异,并且除以一个日历年的平均长度(以400天为单位的天数)(365.2425),您将获得更准确的结果:

datediff(day,{start-date},{end-date},) / 365.2425

例如,

select datediff(day,'1 Jan 2000' ,'18 April 2014') / 365.2425

返回14.29461248 - 将其四舍五入到所需的精度。

答案 1 :(得分:10)

您是否尝试过几个月来改变差异,然后以这种方式计算年数?例如30个月/ 12年将是2。5年。

编辑:此SQL查询包含几种计算日期差异的方法:

SELECT CONVERT(date, GetDate() - 912) AS calcDate
      ,DATEDIFF(DAY, GetDate() - 912, GetDate()) diffDays
      ,DATEDIFF(DAY, GetDate() - 912, GetDate()) / 365.0 diffDaysCalc
      ,DATEDIFF(MONTH, GetDate() - 912, GetDate()) diffMonths
      ,DATEDIFF(MONTH, GetDate() - 912, GetDate()) / 12.0 diffMonthsCalc
      ,DATEDIFF(YEAR, GetDate() - 912, GetDate()) diffYears

答案 2 :(得分:4)

我认为365.2425的划分并不是一个很好的方法。没有任何一个部门可以完全准确地使用它(使用365.25也有问题)。

我知道以下脚本会计算出准确的日期差异(尽管可能不是最快速的方式):

observableColleciton.Any(g=>g.IsModelDirty)

进行比较:

        declare @d1 datetime ,@d2 datetime
        --set your dates eg: 
        select @d1 = '1901-03-02'
        select @d2 = '2016-03-01'

        select DATEDIFF(yy, @d1, @d2) -
            CASE WHEN MONTH(@d2) < MONTH(@d1) THEN 1
                 WHEN MONTH(@d2) > MONTH(@d1) THEN 0
                 WHEN DAY(@d2) < DAY(@d1) THEN 1
                 ELSE 0 END

         -- = 114 years

您可以用除法计算小范围,但为什么要冒险?

以下脚本可以帮助测试yeardiff函数(只需交换强制转换(datediff(day,@ d1,@ d2)/ 365.2425作为int),无论函数是什么):

         select datediff(day,@d1 ,@d2) / 365.2425
         -- = 115 years => wrong!

答案 3 :(得分:0)

我找到了更好的解决方案。这样就假设第一个日期小于或等于第二个日期。

declare @dateTable table (date1 datetime, date2 datetime)
insert into @dateTable 
    select '2017-12-31', '2018-01-02' union
    select '2017-01-03', '2018-01-02' union 
    select '2017-01-02', '2018-01-02' union
    select '2017-01-01', '2018-01-02' union
    select '2016-12-01', '2018-01-02' union
    select '2016-01-03', '2018-01-02' union
    select '2016-01-02', '2018-01-02' union
    select '2016-01-01', '2018-01-02' 
select date1, date2, 
        case when ((DATEPART(year, date1) < DATEPART(year, date2)) and 
                    ((DATEPART(month, date1) <= DATEPART(month, date2)) and 
(DATEPART(day, date1) <= DATEPART(day, date2)) ))
                    then DATEDIFF(year, date1, date2)
            when (DATEPART(year, date1) < DATEPART(year, date2))
                    then DATEDIFF(year, date1, date2) - 1
            when (DATEPART(year, date1) = DATEPART(year, date2))
                    then 0
        end [YearsOfService]
from @dateTable

date1                   date2                   YearsOfService
----------------------- ----------------------- --------------
2016-01-01 00:00:00.000 2018-01-02 00:00:00.000 2
2016-01-02 00:00:00.000 2018-01-02 00:00:00.000 2
2016-01-03 00:00:00.000 2018-01-02 00:00:00.000 1
2016-12-01 00:00:00.000 2018-01-02 00:00:00.000 1
2017-01-01 00:00:00.000 2018-01-02 00:00:00.000 1
2017-01-02 00:00:00.000 2018-01-02 00:00:00.000 1
2017-01-03 00:00:00.000 2018-01-02 00:00:00.000 0
2017-12-31 00:00:00.000 2018-01-02 00:00:00.000 0

答案 4 :(得分:0)

您想要年差,但是当未来日期的“一年中的某一天”小于过去日期的“年份”时减 1。像这样:

SELECT *
,DATEDIFF(YEAR, [Begin_date], [End_Date])
 + CASE WHEN CAST(DATENAME(DAYOFYEAR, [End_Date]) AS INT)
          >= CAST(DATENAME(DAYOFYEAR, [Begin_date]) AS INT)
   THEN 0 ELSE -1 END
 AS 'Age in Years'
from [myTable];

答案 5 :(得分:0)

对我来说,我计算的是天数差异

Declare @startDate datetime
Declare @endDate datetime
Declare @diff int
select @diff=datediff(day,@startDate,@endDate)
if (@diff>=365) then select '1Year'
if (@diff>=730) then select '2Years'

-----etc