How to calculate age in T-SQL with years, months, and days

后端 未结 24 1541
无人共我
无人共我 2020-11-22 05:42

What would be the best way to calculate someone\'s age in years, months, and days in T-SQL (SQL Server 2000)?

The datediff function doesn\'t handle year

24条回答
  •  伪装坚强ぢ
    2020-11-22 06:21

    Implemented by arithmetic with ISO formatted date.

    declare @now date,@dob date, @now_i int,@dob_i int, @days_in_birth_month int
    declare @years int, @months int, @days int
    set @now = '2013-02-28' 
    set @dob = '2012-02-29' -- Date of Birth
    
    set @now_i = convert(varchar(8),@now,112) -- iso formatted: 20130228
    set @dob_i = convert(varchar(8),@dob,112) -- iso formatted: 20120229
    set @years = ( @now_i - @dob_i)/10000
    -- (20130228 - 20120229)/10000 = 0 years
    
    set @months =(1200 + (month(@now)- month(@dob))*100 + day(@now) - day(@dob))/100 %12
    -- (1200 + 0228 - 0229)/100 % 12 = 11 months
    
    set @days_in_birth_month = day(dateadd(d,-1,left(convert(varchar(8),dateadd(m,1,@dob),112),6)+'01'))
    set @days = (sign(day(@now) - day(@dob))+1)/2 * (day(@now) - day(@dob))
              + (sign(day(@dob) - day(@now))+1)/2 * (@days_in_birth_month - day(@dob) + day(@now))
    -- ( (-1+1)/2*(28 - 29) + (1+1)/2*(29 - 29 + 28))
    -- Explain: if the days of now is bigger than the days of birth, then diff the two days
    --          else add the days of now and the distance from the date of birth to the end of the birth month 
    select @years,@months,@days -- 0, 11, 28 
    

    Test Cases

    The approach of days is different from the accepted answer, the differences shown in the comments below:

           dob        now  years  months  days 
    2012-02-29 2013-02-28      0      11    28  --Days will be 30 if calculated by the approach in accepted answer. 
    2012-02-29 2016-02-28      3      11    28  --Days will be 31 if calculated by the approach in accepted answer, since the day of birth will be changed to 28 from 29 after dateadd by years. 
    2012-02-29 2016-03-31      4       1     2
    2012-01-30 2016-02-29      4       0    30
    2012-01-30 2016-03-01      4       1     2  --Days will be 1 if calculated by the approach in accepted answer, since the day of birth will be changed to 30 from 29 after dateadd by years.
    2011-12-30 2016-02-29      4       1    30
    

    An short version of Days by case statement:

    set @days = CASE WHEN day(@now) >= day(@dob) THEN day(@now) - day(@dob)
                     ELSE @days_in_birth_month - day(@dob) + day(@now) END
    

    If you want the age of years and months only, it could be simpler

    set @years = ( @now_i/100 - @dob_i/100)/100
    set @months =(12 + month(@now) - month(@dob))%12 
    select @years,@months -- 1, 0
    

    NOTE: A very useful link of SQL Server Date Formats

提交回复
热议问题