MySQL Рассчитать возраст по месяцам и дням

Я хочу отображать данные о возрасте пациентов.


 mysql> выберите nama, gender, dob, TIMESTAMPDIFF (YEAR, dob, now ()) как возраст от сампеладжа;
 + ------------------ + -------- + ------------ + ------ +
 |  Нама |  пол |  dob |  возраст |
 + ------------------ + -------- + ------------ + ------ +
 |  Rizkiyandi |  1 |  2010-05-21 |  4 |
 |  Сити Ходия |  0 |  1980-03-15 |  34 |
 |  Aisyah Az-zahra |  0 |  1986-08-17 |  28 |
 |  Paritem |  0 |  2005-12-13 |  8 |
 |  Нгадимин |  1 |  2014-08-28 |  0 |
 + ------------------ + -------- + ------------ + ------ +

 10 строк в наборе (0,00 сек)

Здесь есть проблема, когда есть 4-дневный ребенок, который считается возрастом 0 лет. Я хочу получить такой результат

 + ------------------ + -------- + ------------ + ------ + - ------ + ------ +
 |  Нама |  пол |  dob |  год |  месяц |  день |
 + ------------------ + -------- + ------------ + ------ + - ------ + ------ +
 |  Rizkiyandi |  1 |  2010-05-21 |  4 |  3 |  13 |
 |  Сити Ходия |  0 |  1980-03-15 |  34 |  5 |  18 |
 |  Aisyah Az-zahra |  0 |  1986-08-17 |  28 |  0 |  16 |
 |  Paritem |  0 |  2005-12-13 |  8 |  8 |  20 |
 |  Нгадимин |  1 |  2014-08-28 |  0 |  0 |  6 |
 + ------------------ + -------- + ------------ + ------ + - ------ + ------ +

Вы можете использовать modulo для определения количества месяцев и дней:

SELECT nama , gender , dob , TIMESTAMPDIFF( YEAR, dob, now() ) as _year , TIMESTAMPDIFF( MONTH, dob, now() ) % 12 as _month , FLOOR( TIMESTAMPDIFF( DAY, dob, now() ) % 30.4375 ) as _day FROM sampelaja 

Результат:

 +-----------------+--------+------------+-------+--------+------+ | nama | gender | dob | _year | _month | _day | +-----------------+--------+------------+-------+--------+------+ | Rizkiyandi | 1 | 2010-05-21 | 4 | 3 | 13 | | Siti Khodijah | 0 | 1980-03-15 | 34 | 5 | 19 | | Aisyah Az-zahra | 0 | 1986-08-17 | 28 | 0 | 17 | | Paritem | 0 | 2005-12-13 | 8 | 8 | 20 | | Ngadimin | 1 | 2014-08-28 | 0 | 0 | 6 | +-----------------+--------+------------+-------+--------+------+ 

Дни рассчитываются между днем ​​рождения от предыдущего месяца до сегодняшнего дня.

Номер 30.4375 Я рассчитал с использованием этой формулы: [ДНИ В ГОД] / 12, где [ДНИ В ГОД] = 365,25

Вы должны уметь вычислять это, используя запрос ниже. Запрос вычисляет точные годы, месяцы и дни.

Эта информация также может быть найдена на странице расчета дней mysql: http://dev.mysql.com/doc/refman/5.0/en/date-calculations.html

 SELECT nama, gender, dob, /* Select the number of years */ TIMESTAMPDIFF( YEAR, dob, CURDATE() ) AS years, /* Select the number of months by adding the number of years to the 'dob' date field */ TIMESTAMPDIFF( MONTH, DATE_ADD( dob , INTERVAL TIMESTAMPDIFF(YEAR,dob,CURDATE()) YEAR ), CURDATE() ) AS months, /* Select the number of days by adding the number of years and number of months to the 'dob' field */ TIMESTAMPDIFF( DAY, DATE_ADD( DATE_ADD( dob , INTERVAL TIMESTAMPDIFF(YEAR,dob,CURDATE() ) YEAR), INTERVAL TIMESTAMPDIFF( MONTH, DATE_ADD( dob , INTERVAL TIMESTAMPDIFF(YEAR,dob,CURDATE()) YEAR ), CURDATE() ) MONTH ), CURDATE() ) AS days FROM sampelaja 

Проблемы в принятом ответе

Метод в принятом ответе хорош, но високосные годы выходят за него в дни рождения. Вот несколько примеров:

 create table sample (dob datetime,now datetime); insert into sample (dob,now)values ('2012-02-29', '2013-02-28'), ('2012-02-29', '2016-02-28'), ('2012-02-29', '2016-03-31'), ('2012-01-30', '2016-02-29'), ('2012-01-30', '2016-03-01'), ('2011-12-30', '2016-02-29'); SELECT date_format(dob,'%Y-%m-%d') , date_format(now,'%Y-%m-%d') , TIMESTAMPDIFF( YEAR, dob, now ) as _year , TIMESTAMPDIFF( MONTH, dob, now ) % 12 as _month , FLOOR( TIMESTAMPDIFF( DAY, dob, now ) % 30.4375 ) as _day FROM sample DOB NOW YEAR MONTH DAY 2012-02-29 2013-02-28 0 11 30 -- 28 days would be better 2012-02-29 2016-02-28 3 11 29 -- 28 days would be better 2012-02-29 2016-03-31 4 1 0 -- 2 days would be better 2012-01-30 2016-02-29 4 0 30 2012-01-30 2016-03-01 4 1 0 -- 2 days should be right 2011-12-30 2016-02-29 4 1 0 -- The right answer should be 4 years 1 months 30 days 

Вот мой подход, используйте только арифметику

 select DATE_FORMAT(dob,'%Y-%m-%d'), DATE_FORMAT(now,'%Y-%m-%d'), FLOOR(( DATE_FORMAT(now,'%Y%m%d') - DATE_FORMAT(dob,'%Y%m%d'))/10000), FLOOR((1200 + DATE_FORMAT(now,'%m%d') - DATE_FORMAT(dob,'%m%d'))/100) %12, (sign(day(now) - day(dob))+1)/2 * (day(now) - day(dob)) + (sign(day(dob) - day(now))+1)/2 * (DAY(STR_TO_DATE(DATE_FORMAT(dob + INTERVAL 1 MONTH,'%Y-%m-01'),'%Y-%m-%d') - INTERVAL 1 DAY) - day(dob) + day(now)) -- Explain: if the days of now is bigger than the days of birth, then diff the two days -- else add the days of now and the distance from the date of birth to the end of the birth month from sample 

Тестовые примеры и результаты:

  DOB NOW YEARS MONTHS DAYS 2012-02-29 2013-02-28 0 11 28 2012-02-29 2016-02-28 3 11 28 2012-02-29 2016-03-31 4 1 2 2012-01-30 2016-02-29 4 0 30 2012-01-30 2016-03-01 4 1 2 2011-12-30 2016-02-29 4 1 30 

В столбе дней в ответ Джагар Чанг есть глюк, когда даты имеют тот же день. Я думаю, что следующие исправления для этого:

 (SELECT CASE sign(day(now)-day(dob)) WHEN 0 THEN 0 WHEN 1 THEN day(now)-day(dob) ELSE (DAY(STR_TO_DATE(DATE_FORMAT(dob + INTERVAL 1 MONTH,'%Y-%m-01'),'%Y-%m-%d')-INTERVAL 1 DAY)-day(dob)+day(now)) END) as days 

Для полноты измененная версия ответа Жаугана будет следовать:

 SELECT FLOOR(( DATE_FORMAT(NOW(),'%Y%m%d') - DATE_FORMAT(dob,'%Y%m%d'))/10000) as year, FLOOR((1200 + DATE_FORMAT(NOW(),'%m%d')-DATE_FORMAT(dob,'%m%d'))/100) %12 as month, CASE sign(day(NOW())-day(dob)) WHEN 0 THEN 0 WHEN 1 THEN day(NOW())-day(dob) ELSE (DAY(STR_TO_DATE(DATE_FORMAT(dob + INTERVAL 1 MONTH,'%Y-%m-01'),'%Y-%m-%d')-INTERVAL 1 DAY)-day(dob)+day(NOW())) END as day FROM sampelaja 

Это запрос, который я использую для расчета возраста в годах, месяцах и днях

 SELECT nama, gender, dob ,DATE_FORMAT(CURDATE(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(CURDATE(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS years ,PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(dob, '%Y%m') ) AS months ,DATEDIFF(CURDATE(),dob) AS days FROM sampelaja 
 SELECT TIMESTAMPDIFF(year, dt.dt, NOW()) AS y, TIMESTAMPDIFF(month, dt.dt, NOW())%12 AS m, TIMESTAMPDIFF ( day, DATE_ADD( adddate(curdate(), day( dt.dt) - day(curdate())), interval -(day( dt.dt)>day(curdate())) month), curdate()) as days FROM (select date('1975-08-07') as dt ) as dt;