计算 SQL 岁

Calculating Age of Years in SQL

我需要一些关于 SQL Server 2012 的帮助,试图计算报告的老化年份字段。

基本上,我有两个字段 StartDateTime 和 EndDateTime,下面是一些示例数据:

StartDateTime                 EndDateTime

 2006-10-10 16:08:13.523      2008-04-11 00:00:00.000
 2016-05-11 13:03:48.093      2016-06-16 00:00:00.000
 2016-08-01 12:44:42.990      2016-08-01 00:00:00.000
 2016-05-20 17:33:27.957      2016-05-25 00:00:00.000
 2006-10-19 21:41:41.350      NULL

我目前正在尝试制作一个 AgingYears 字段来计算两个字段之间的老化年份(尽可能准确。)并且当 EndDateTime 为 NULL 时,它应该计算 GETDATE() 和 StartDateTime 之间的差异。当 StartDateTime 大于 EndDateTime(我不知道为什么我有这样的数据,但我有),那么它应该 return 返回 0.

我尝试根据我发现的相关网站编写一些代码,但这对我帮助不大,这就是我遇到的问题:

DATEDIFF(YY, StartDateTime, EndDateTime) - 
    CASE
        WHEN DATEADD(YY,DATEDIFF(YY,StartDateTime, EndDateTime),StartDateTime)
            > A.[END_DTTM] 
        THEN DATEDIFF(YY, StartDateTime, EndDateTime)- 1
        ELSE DATEDIFF(YY, StartDateTime, EndDateTime)
    END AS AgeInYears,

任何对我的代码的帮助将不胜感激。

小心闰年。你希望2月29日到2月28日如何对待?

case
    when year(coalesce(EndDateTime, getdate()) > year(StartDateTime)
    then
        datediff(year, StartDateTime, coalesce(EndDateTime, getdate())) -
        case
            when
                EndDateTime is not null and 
                    datepart(month, EndDateTime) < datepart(month, StartDateTime)
                or  datepart(month, EndDateTime) = datepart(month, StartDateTime)
                and datepart(day,   EndDateTime) < datepart(day,   StartDateTime)
            then 1
            when
                EndDateTime is null and
                    datepart(month, getdate())   < datepart(month, StartDateTime)
                or  datepart(month, getdate())   = datepart(month, StartDateTime)
                and datepart(day,   getdate())   < datepart(day,   StartDateTime)
            then 1
            else 0
        end
    else 0
end

我将 EndDateTimegetdate() 情况分开主要是因为在长行上没有滚动条看起来更好。

这里有一种方法可以调整该逻辑并捕捉闰日条件,将其视为整年,即使日期并不严格重合。如果按照我上面写的方式保持 "split" 逻辑,则需要在两个分支中复制此表达式(替换为 getdate() forEndDateTimeeverywhere except theis null` 测试)。

            when
                EndDateTime is not null and
                    datepart(month, EndDateTime)     < datepart(month, StartDateTime)
                 or datepart(month, EndDateTime)     = datepart(month, StartDateTime)
                and datepart(day,   EndDateTime)     < datepart(day,   StartDateTime)
                and not -- here's one way to catch the leap day condition
                (
                    -- adding one day this way is deprecated and only works with datetime
                    and datepart(month, StartDateTime + 1) > datepart(month, StartDateTime)
                    and datepart(month, EndDateTime + 1)   > datepart(month, EndDateTime)
                )

http://rextester.com/SBH69843

顺便说一句,一旦您理解了这种方法,就有一种方法可以使用 yyyymmdd 格式的数字算术来压缩相同的逻辑。

(
cast(convert(varchar(8), @EndDateTime, 120) as int) -
cast(convert(varchar(8), @StartDateTime, 120) as int)
) / 10000

上面所有复杂的逻辑都是借用了减法中的年位。这几乎是一回事。

我觉得应该是这样的:

SELECT StartDate
    , EndDate
    , CASE 
        WHEN DATEDIFF(YY, StartDate, ISNULL(EndDate, GETDATE())) < 0
            THEN 0
        ELSE DATEDIFF(YY, StartDate, ISNULL(EndDate, GETDATE()))
        END AS AgingYears
FROM YourTableName