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

时间:2020-12-08 01:24:55

I receive reports in which the data is ETL to the DB automatically. I extract and transform some of that data to load it somewhere else. One thing I need to do is a DATEDIFF but the year needs to be exact (i.e., 4.6 years instead of rounding up to five years.

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

The following is my script:

以下是我的脚本:

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

The 'Age_In_Years' column is being rounded. How do I get the exact date in years?

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

3 个解决方案

#1


9  

Have you tried getting the difference in months instead and then calculating the years that way? For example 30 months / 12 would be 2.5 years.

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

Edit: This SQL query contains several approaches to calculate the date difference:

编辑:此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


11  

All datediff() does is compute the number of period boundaries crossed between to dates. For instance

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

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

returns 1.

返回1。

You'll get a more accurate result if you compute the difference between the two dates in days and divide by the mean length of a calendar year in days over a 400 year span (365.2425):

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

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

For instance,

例如,

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

return 14.29461248 — just round it to the desired precision.

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

#3


2  

I think that division by 365.2425 is not a good way to do this. No division can to this completely accurately (using 365.25 also has issues).

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

I know the following script calculates an accurate date difference (though might not be the most speedy way):

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

        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

For comparison:

为了比较:

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

You might be able to calculate small ranges with division, but why take a chance??

你可能能够用除法计算小范围,但为什么要冒险?

The following script can help to test yeardiff functions (just swap cast(datediff(day,@d1,@d2) / 365.2425 as int) to whatever the function is):

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

   declare @d1 datetime set @d1 = '1900-01-01'

   while(@d1 < '2016-01-01')
   begin
    declare @d2 datetime set @d2 = '2016-04-01'

    while(@d2 >= '1900-01-01')
    begin
        if (@d1 <= @d2 and dateadd(YEAR,     cast(datediff(day,@d1,@d2) / 365.2425 as int)      , @d1) > @d2)
        begin
            select 'not a year!!', @d1, @d2, cast(datediff(day,@d1,@d2) / 365.2425 as int)
        end

        set @d2 = dateadd(day,-1,@d2)
    end

    set @d1 = dateadd(day,1,@d1)
  end

#1


9  

Have you tried getting the difference in months instead and then calculating the years that way? For example 30 months / 12 would be 2.5 years.

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

Edit: This SQL query contains several approaches to calculate the date difference:

编辑:此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


11  

All datediff() does is compute the number of period boundaries crossed between to dates. For instance

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

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

returns 1.

返回1。

You'll get a more accurate result if you compute the difference between the two dates in days and divide by the mean length of a calendar year in days over a 400 year span (365.2425):

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

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

For instance,

例如,

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

return 14.29461248 — just round it to the desired precision.

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

#3


2  

I think that division by 365.2425 is not a good way to do this. No division can to this completely accurately (using 365.25 also has issues).

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

I know the following script calculates an accurate date difference (though might not be the most speedy way):

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

        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

For comparison:

为了比较:

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

You might be able to calculate small ranges with division, but why take a chance??

你可能能够用除法计算小范围,但为什么要冒险?

The following script can help to test yeardiff functions (just swap cast(datediff(day,@d1,@d2) / 365.2425 as int) to whatever the function is):

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

   declare @d1 datetime set @d1 = '1900-01-01'

   while(@d1 < '2016-01-01')
   begin
    declare @d2 datetime set @d2 = '2016-04-01'

    while(@d2 >= '1900-01-01')
    begin
        if (@d1 <= @d2 and dateadd(YEAR,     cast(datediff(day,@d1,@d2) / 365.2425 as int)      , @d1) > @d2)
        begin
            select 'not a year!!', @d1, @d2, cast(datediff(day,@d1,@d2) / 365.2425 as int)
        end

        set @d2 = dateadd(day,-1,@d2)
    end

    set @d1 = dateadd(day,1,@d1)
  end