1

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

I have a problem with age calculation on Sql Server 2005. I have a customers table which has date of birth column. What i want is to create view which has an age column and this age column should show the age of a person by subtracting the date of birth from today(pretty simple).

I found a couple of good resources here but what i want exactly is to show the age by years and months. eg.(47 yrs, 3 months). This means i want to have both the year and month values and i want to add a string (either 'years', 'yrs', 'y', 'months', 'mon', 'm', ...) to the appropriate value and display it as eg. (25 years, 2 months). And if the person's age is just for example 3 months, it should display '3 months', not '0 years, 3 months'.

If the person's age is some years without any months, it should display eg. '5 years' not '5 years, 0 months'

Oh, I have already done that using c# but i want to create a column on the sql view so that i can just populate my gridview using the view without doing any calculation on my c# code. If it helps i can post my c# code here. Thanks

Community
  • 1
  • 1
EngAbth9
  • 31
  • 9

4 Answers4

1

Here's a format_age function:

CREATE FUNCTION format_age(
    @DOB datetime,
    @now datetime
)
RETURNS nvarchar(30)
BEGIN
    DECLARE @years int, @months int;
    IF @DOB > @now RETURN N'not born yet';
    SET @years = DATEDIFF(year, @DOB, @now);
    IF MONTH(@DOB) * 100 + DAY(@DOB) > MONTH(@now) * 100 + DAY(@now)
        SET @years = @years - 1;
    SET @months = DATEDIFF(month, DATEADD(year, @years, @DOB), @now);
    IF DAY(@DOB) > DAY(@now)
        SET @months = @months - 1;
    RETURN CASE
        WHEN @years = 0 THEN CONVERT(nvarchar(30), @months) + N' months'
        WHEN @months = 0 THEN CONVERT(nvarchar(30), @years) + N' years'
        ELSE CONVERT(nvarchar(30), @years) + N' years, ' +
            CONVERT(nvarchar(30), @months) + N' months'
    END;
END
GO

Here's some test cases:

SELECT '2011-02-16' AS dt, dbo.format_age('2011-02-16', '2012-03-16') AS age UNION
SELECT '2011-03-16',       dbo.format_age('2011-03-16', '2012-03-16')        UNION
SELECT '2011-03-17',       dbo.format_age('2011-03-17', '2012-03-16')        UNION
SELECT '2012-03-16',       dbo.format_age('2012-03-16', '2012-03-16')        UNION
SELECT '2012-03-17',       dbo.format_age('2012-03-17', '2012-03-16')

And here's the result*:

| dt          | age               |
|-------------|-------------------|
| 2011-02-16  | 1 years, 1 months |
| 2011-03-16  | 1 years           |
| 2011-03-17  | 11 months         |
| 2012-03-16  | 0 months          |
| 2012-03-17  | not born yet      |

*Reference date is 2012-03-16

KyleMit
  • 30,350
  • 66
  • 462
  • 664
Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
  • shows this error when executing the query on sql server management studio. Msg 139, Level 15, State 1, Procedure format_age, Line 0 Cannot assign a default value to a local variable. Msg 137, Level 15, State 2, Procedure format_age, Line 10 Must declare the scalar variable "@years". Msg 139, Level 15, State 1, Procedure format_age, Line 0 Cannot assign a default value to a local variable. Msg 137, Level 15, State 2, Procedure format_age, Line 13 Must declare the scalar variable "@months". Msg 137, Level 15, State 2, Procedure format_age, Line 15 Must declare the scalar variable "@years". – EngAbth9 Mar 17 '12 at 19:04
  • Assigning a value with the `DECLARE` statement was introduced in SQL Server 2008. I updated the answer to split it up into a separate `DECLARE` and `SET`. – Markus Jarderot Mar 17 '12 at 22:22
  • Tested on SQL Server 2000, and it seems to work. – Markus Jarderot Mar 17 '12 at 22:36
0

I think you should consider localization issues with that solution (and different standards to calculate the age in different countries). If you do not care about that you may:

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
0

You need something like this:

SELECT *,
  case when DATEDIFF(MONTH, Birthday, GETDATE()) < 12
  then 
    CONVERT(nvarchar(16), DATEDIFF(MONTH, Birthday, GETDATE())) + ' months'
  else 
    CONVERT(nvarchar(16), DATEDIFF(YEAR, Birthday, GETDATE())) + ' years, ' + 
    CONVERT(nvarchar(16), DATEDIFF(MONTH, Birthday, GETDATE()) % 12 ) + ' months'
  end 
FROM dbo.CUSTOMER
Phil
  • 42,255
  • 9
  • 100
  • 100
0

Maybe something like this:

Test data

DECLARE @tbl TABLE(birthDay DATETIME)
INSERT INTO @tbl
VALUES
    ('2004-04-05'),
    ('2001-02-05')

Query

;WITH Years
AS
(   
    SELECT
        DATEDIFF(yy, tbl.birthDay, GETDATE()) - CASE WHEN (MONTH(tbl.birthDay) > MONTH(GETDATE())) OR (MONTH(tbl.birthDay) = MONTH(GETDATE()) AND DAY(tbl.birthDay) > DAY(GETDATE())) THEN 1 ELSE 0 END AS Years,
        tbl.birthDay
    FROM
        @tbl AS tbl 
), BithDayWithMonth
AS
(
    SELECT
        Years.Years,
        DATEDIFF(m, years.tmp, GETDATE()) - CASE WHEN DAY(Years.birthDay) > DAY(GETDATE()) THEN 1 ELSE 0 END AS Months
    FROM
        (
            SELECT
                DATEADD(yy, Years.Years, Years.birthDay) AS tmp,
                Years.Years,
                Years.birthDay
            FROM
                Years
        ) AS years
)
SELECT
    (CASE WHEN BithDayWithMonth.Years=0 THEN '' ELSE CAST(BithDayWithMonth.Years AS VARCHAR(10))+' years' END)+
    (CASE WHEN BithDayWithMonth.Months=0 THEN '' ELSE (CASE WHEN NOT BithDayWithMonth.Years=0 THEN ', ' ELSE '' END) +
    CAST(BithDayWithMonth.Years AS VARCHAR(10))+' months' END)
FROM
    BithDayWithMonth
Arion
  • 31,011
  • 10
  • 70
  • 88
  • Query executes successfully but there are some irregular values like 24 years, 24 months (using 3/17/2012 as now and 3/20/1987 as Birth Date) – EngAbth9 Mar 17 '12 at 19:07