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?
I've done a lot of thinking and searching about this and I have 3 solutions that
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.