How to calculate age (in years) based on Date of Birth and getDate()

前端 未结 30 2092
死守一世寂寞
死守一世寂寞 2020-11-22 02:08

I have a table listing people along with their date of birth (currently a nvarchar(25))

How can I convert that to a date, and then calculate their age in years?

相关标签:
30条回答
  • 2020-11-22 02:30

    You need to consider the way the datediff command rounds.

    SELECT CASE WHEN dateadd(year, datediff (year, DOB, getdate()), DOB) > getdate()
                THEN datediff(year, DOB, getdate()) - 1
                ELSE datediff(year, DOB, getdate())
           END as Age
    FROM <table>
    

    Which I adapted from here.

    Note that it will consider 28th February as the birthday of a leapling for non-leap years e.g. a person born on 29 Feb 2020 will be considered 1 year old on 28 Feb 2021 instead of 01 Mar 2021.

    0 讨论(0)
  • 2020-11-22 02:30

    Just check whether the below answer is feasible.

    DECLARE @BirthDate DATE = '09/06/1979'
    
    SELECT 
     (
     YEAR(GETDATE()) - YEAR(@BirthDate) - 
     CASE  WHEN (MONTH(GETDATE()) * 100) + DATEPART(dd, GETDATE()) >     
     (MONTH(@BirthDate) * 100) + DATEPART(dd, @BirthDate)
     THEN 1             
     ELSE 0             
     END        
     )
    
    0 讨论(0)
  • 2020-11-22 02:30

    Ed Harper's solution is the simplest I have found which never returns the wrong answer when the month and day of the two dates are 1 or less days apart. I made a slight modification to handle negative ages.

    DECLARE @D1 AS DATETIME, @D2 AS DATETIME
    SET @D2 = '2012-03-01 10:00:02'
    SET @D1 = '2013-03-01 10:00:01'
    SELECT
       DATEDIFF(YEAR, @D1,@D2)
       +
       CASE
          WHEN @D1<@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) > @D2
          THEN - 1
          WHEN @D1>@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) < @D2
          THEN 1
          ELSE 0
       END AS AGE
    
    0 讨论(0)
  • 2020-11-22 02:30
    DECLARE @FromDate DATETIME = '1992-01-2623:59:59.000', 
            @ToDate   DATETIME = '2016-08-10 00:00:00.000',
            @Years INT, @Months INT, @Days INT, @tmpFromDate DATETIME
    SET @Years = DATEDIFF(YEAR, @FromDate, @ToDate)
     - (CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @FromDate, @ToDate),
              @FromDate) > @ToDate THEN 1 ELSE 0 END) 
    
    
    SET @tmpFromDate = DATEADD(YEAR, @Years , @FromDate)
    SET @Months =  DATEDIFF(MONTH, @tmpFromDate, @ToDate)
     - (CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH, @tmpFromDate, @ToDate),
              @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 
    
    SET @tmpFromDate = DATEADD(MONTH, @Months , @tmpFromDate)
    SET @Days =  DATEDIFF(DAY, @tmpFromDate, @ToDate)
     - (CASE WHEN DATEADD(DAY, DATEDIFF(DAY, @tmpFromDate, @ToDate),
              @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 
    
    SELECT @FromDate FromDate, @ToDate ToDate, 
           @Years Years,  @Months Months, @Days Days
    
    0 讨论(0)
  • 2020-11-22 02:31

    There are issues with leap year/days and the following method, see the update below:

    try this:

    DECLARE @dob  datetime
    SET @dob='1992-01-09 00:00:00'
    
    SELECT DATEDIFF(hour,@dob,GETDATE())/8766.0 AS AgeYearsDecimal
        ,CONVERT(int,ROUND(DATEDIFF(hour,@dob,GETDATE())/8766.0,0)) AS AgeYearsIntRound
        ,DATEDIFF(hour,@dob,GETDATE())/8766 AS AgeYearsIntTrunc
    

    OUTPUT:

    AgeYearsDecimal                         AgeYearsIntRound AgeYearsIntTrunc
    --------------------------------------- ---------------- ----------------
    17.767054                               18               17
    
    (1 row(s) affected)
    

    UPDATE here are some more accurate methods:

    BEST METHOD FOR YEARS IN INT

    DECLARE @Now  datetime, @Dob datetime
    SELECT   @Now='1990-05-05', @Dob='1980-05-05'  --results in 10
    --SELECT @Now='1990-05-04', @Dob='1980-05-05'  --results in  9
    --SELECT @Now='1989-05-06', @Dob='1980-05-05'  --results in  9
    --SELECT @Now='1990-05-06', @Dob='1980-05-05'  --results in 10
    --SELECT @Now='1990-12-06', @Dob='1980-05-05'  --results in 10
    --SELECT @Now='1991-05-04', @Dob='1980-05-05'  --results in 10
    
    SELECT
        (CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000 AS AgeIntYears
    

    you can change the above 10000 to 10000.0 and get decimals, but it will not be as accurate as the method below.

    BEST METHOD FOR YEARS IN DECIMAL

    DECLARE @Now  datetime, @Dob datetime
    SELECT   @Now='1990-05-05', @Dob='1980-05-05' --results in 10.000000000000
    --SELECT @Now='1990-05-04', @Dob='1980-05-05' --results in  9.997260273973
    --SELECT @Now='1989-05-06', @Dob='1980-05-05' --results in  9.002739726027
    --SELECT @Now='1990-05-06', @Dob='1980-05-05' --results in 10.002739726027
    --SELECT @Now='1990-12-06', @Dob='1980-05-05' --results in 10.589041095890
    --SELECT @Now='1991-05-04', @Dob='1980-05-05' --results in 10.997260273973
    
    SELECT 1.0* DateDiff(yy,@Dob,@Now) 
        +CASE 
             WHEN @Now >= DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)) THEN  --birthday has happened for the @now year, so add some portion onto the year difference
               (  1.0   --force automatic conversions from int to decimal
                  * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
                  / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
               )
             ELSE  --birthday has not been reached for the last year, so remove some portion of the year difference
               -1 --remove this fractional difference onto the age
               * (  -1.0   --force automatic conversions from int to decimal
                    * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
                    / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
                 )
         END AS AgeYearsDecimal
    
    0 讨论(0)
  • 2020-11-22 02:31

    What about a solution with only date functions, not math, not worries about leap year

    CREATE FUNCTION dbo.getAge(@dt datetime) 
    RETURNS int
    AS
    BEGIN
        RETURN 
            DATEDIFF(yy, @dt, getdate())
            - CASE 
                WHEN 
                    MONTH(@dt) > MONTH(GETDATE()) OR 
                    (MONTH(@dt) = MONTH(GETDATE()) AND DAY(@dt) > DAY(GETDATE())) 
                THEN 1 
                ELSE 0 
            END
    END
    
    0 讨论(0)
提交回复
热议问题