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

前端 未结 30 2448
死守一世寂寞
死守一世寂寞 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:37

    I've done a lot of thinking and searching about this and I have 3 solutions that

    • calculate age correctly
    • are short (mostly)
    • are (mostly) very understandable.

    Here are testing values:

    DECLARE @NOW DATETIME = '2013-07-04 23:59:59' 
    DECLARE @DOB DATETIME = '1986-07-05' 
    

    Solution 1: I found this approach in one js library. It's my favourite.

    DATEDIFF(YY, @DOB, @NOW) - 
      CASE WHEN DATEADD(YY, DATEDIFF(YY, @DOB, @NOW), @DOB) > @NOW THEN 1 ELSE 0 END
    

    It's actually adding difference in years to DOB and if it is bigger than current date then subtracts one year. Simple right? The only thing is that difference in years is duplicated here.

    But if you don't need to use it inline you can write it like this:

    DECLARE @AGE INT = DATEDIFF(YY, @DOB, @NOW)
    IF DATEADD(YY, @AGE, @DOB) > @NOW
    SET @AGE = @AGE - 1
    

    Solution 2: This one I originally copied from @bacon-bits. It's the easiest to understand but a bit long.

    DATEDIFF(YY, @DOB, @NOW) - 
      CASE WHEN MONTH(@DOB) > MONTH(@NOW) 
        OR MONTH(@DOB) = MONTH(@NOW) AND DAY(@DOB) > DAY(@NOW) 
      THEN 1 ELSE 0 END
    

    It's basically calculating age as we humans do.


    Solution 3: My friend refactored it into this:

    DATEDIFF(YY, @DOB, @NOW) - 
      CEILING(0.5 * SIGN((MONTH(@DOB) - MONTH(@NOW)) * 50 + DAY(@DOB) - DAY(@NOW)))
    

    This one is the shortest but it's most difficult to understand. 50 is just a weight so the day difference is only important when months are the same. SIGN function is for transforming whatever value it gets to -1, 0 or 1. CEILING(0.5 * is the same as Math.max(0, value) but there is no such thing in SQL.

提交回复
热议问题