How to get an age from a D.O.B field in MySQL?

后端 未结 13 1538
鱼传尺愫
鱼传尺愫 2020-11-29 07:01

I need to calculate the age of a \"customer\" from their date of birth.

I have tried to use the following:

DATEDIFF(year, customer.dob, \"2010

相关标签:
13条回答
  • 2020-11-29 07:36

    Bryan Denny's answer is more correct than the accepted answer (I wasn't sure how to put this in somewhere other than a new answer; this is my first time on StackOverflow).

    Marcos' first attempt:

    select DATEDIFF(customer.dob, '2010-01-01') / 365.25 as age
    

    will firstly yield a negative result (the arguments to DATEDIFF are in the wrong order), and secondly will produce inaccurate results for some dates, e.g.:

    SELECT DATEDIFF('2010-05-11','1984-05-11') / 365.25 AS age
    

    produces the result:

    25.9986
    

    You can't just simply always round up, because that will also cause inaccurate results for other inputs.

    Marcos' second attempt:

    SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(customer.dob,'2010-01-01')), ‘%Y’)+0 AS age
    

    Again, the arguments are in the wrong order, except this time instead of just producing a negative number, the FROM_DAYS() function does not work correctly with negative input. Secondly, if we look closer at the output of the FROM_DAYS() function:

    select from_days(datediff('2010-09-16','1984-05-11'));
    

    The result of the above is:

    0026-05-08
    

    which is literally "8th of May, Year 26 (after 0)". Keep in mind that for datetime types, there is no month "0", so if you wanted to use this format to measure a date interval with months included, you'd have to subtract 1 from the month. Similarly, with the day component, there is no "0", so the result is not what you'd expect for this problem when the date happens to be the birthday:

    select from_days(datediff('2010-05-11','1984-05-11'));
    

    produces:

    0025-12-31
    

    which if we shorten using Marcos' date formatting gives us "25", which is an incorrect calculation of age.

    Bryan Denny's answer is correct in all these edge cases. His formula is quite clever:

    SELECT DATE_FORMAT(reference, '%Y') - DATE_FORMAT(birthdate, '%Y') - (DATE_FORMAT(reference, '00-%m-%d') < DATE_FORMAT(birthdate, '00-%m-%d')) AS age
    

    The first part calculates the difference in years between the two dates. So if we take "2010" and "1984" as reference and birthdate respectively, the result is "26". The second part then calculates essentially "Does the birthdate month and day occur after the reference month and day?" If it does, it "hasn't happened yet", so we need to subtract an additional 1 from the year difference to make up for this. This is taken care of by the result of the < comparison, which returns 1 if true and 0 if false.

    So, full examples:

    1)

    Reference date: 2010-05-10;
    Birthdate: 1984-05-11
    
    Year difference = 2010 - 1984 = 26
    Month and day comparison: May 10th < May 11th? Yes => subtract an additional year
    Calculated age: 25 years
    

    2)

    Reference date: 2010-05-11;
    Birthdate: 1984-05-11
    
    Year difference = 2010 - 1984 = 26
    Month and day comparison: May 11th < May 11th? No => subtract 0
    Calculated age: 26 years
    

    I hope this makes things clearer for people!

    0 讨论(0)
  • 2020-11-29 07:39

    A few ways:

    select DATEDIFF(customer.dob, '2010-01-01') / 365.25 as age
    
    SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(customer.dob,'2010-01-01')), ‘%Y’)+0 AS age
    

    Hope this helps you

    0 讨论(0)
  • 2020-11-29 07:40

    Assumed the given date is greater than the current date,

    1.Find the total no of days b/w the current date and the given date.

    -> DATEDIFF(NOW(),'1988-05-01')

    2.Find the no of years from the calculated no of days.

    -> DATEDIFF(NOW(),'1988-05-01')/365.25

    3.The age should be the completed no of years by a person. To get it, we can use 'floor' to the calculated no of years.

    -> FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25)

    Example: SELECT FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25) AS age;

    0 讨论(0)
  • 2020-11-29 07:43

    Depends on your needs - int and float functions provided.
    - Your business rules may differ so adjust accordingly

    DROP FUNCTION IF EXISTS `age`; 
    CREATE FUNCTION `age` (
      `pdate_begin` DATE,
      `pdate_end` DATETIME
    ) RETURNS INT(11) UNSIGNED   
    COMMENT 'Calc age between two dates as INT' 
    DETERMINISTIC NO SQL SQL SECURITY DEFINER
    RETURN floor(datediff(pdate_end, pdate_begin) / 365.25) ;
    
    DROP FUNCTION IF EXISTS `age_strict`; 
    CREATE FUNCTION `age_strict` (
      `pdate_begin` DATE,
      `pdate_end` DATETIME
    ) RETURNS decimal(10,4)
    COMMENT 'Calc age between two dates as DECIMAL .4' 
    DETERMINISTIC NO SQL SQL SECURITY DEFINER
    RETURN round(datediff(pdate_end, pdate_begin) / 365.25, 4) ;
    
    -- test harness
    select 
        age(dob, now())        as age_int,
        age_strict(dob, now()) as age_dec
        from customer 
        where dob is not null 
        order by age(dob,now()) desc;
    
    -- test results
    dob,                  age_int,            age_dec
    1981-01-01 00:00:00        33             33.9713
    1987-01-09 00:00:00        27             27.9507
    2014-11-25 00:00:00         0              0.0739
    
    0 讨论(0)
  • 2020-11-29 07:43
    DATE_FORMAT(FROM_DAYS(DATEDIFF(CURDATE(),'1869-10-02')), '%Y')+0 AS age;
    

    Above MySQL query has been tested and verified. It will give you exact age in years. I have taken this idea from Marcos answer and switched DATEDIFF() parameters.

    0 讨论(0)
  • 2020-11-29 07:44

    The below sql works fine for me. Always use CURRENT_DATE with dob to calculate the actual age .

    SELECT 
        DATE_FORMAT(
            FROM_DAYS(
                DATEDIFF(CURRENT_DATE, dob)
            ),
            '%y Years %m Months %d Days'
        ) AS age 
    FROM 
        users
    
    0 讨论(0)
提交回复
热议问题