Ответ Брайана Денни является более правильным, чем принятый ответ (я не был уверен, как вставить это где-то, кроме нового ответа; это мой первый раз в StackOverflow).
Первая попытка Маркоса:
select DATEDIFF(customer.dob, '2010-01-01') / 365.25 as age
во-первых, приведет к отрицательному результату (аргументы DATEDIFF расположены в неправильном порядке), а во-вторых, приведет к получению неточных результатов для некоторых дат, например, :
SELECT DATEDIFF('2010-05-11','1984-05-11') / 365.25 AS age
дает результат:
25.9986
Вы не можете просто всегда округлять, потому что это также приведет к неточным результатам для других входных данных.
Вторая попытка Маркоса:
SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(customer.dob,'2010-01-01')), ‘%Y’)+0 AS age
Опять же, аргументы в неправильном порядке, за исключением того, что вместо того, чтобы просто генерировать отрицательное число, функция FROM_DAYS () не работает правильно с отрицательным вводом. Во-вторых, если мы посмотрим поближе на вывод функции FROM_DAYS ():
select from_days(datediff('2010-09-16','1984-05-11'));
Результат вышеописанного:
0026-05-08
что буквально "8 мая, год 26 (после 0)". Помните, что для типов даты и времени нет месяца «0», поэтому, если вы хотите использовать этот формат для измерения интервала дат с включенными месяцами, вам придется вычесть 1 из месяца. Точно так же с компонентом дня нет "0", поэтому результат не тот, который вы ожидаете для этой проблемы, когда дата оказывается днем рождения:
select from_days(datediff('2010-05-11','1984-05-11'));
производит:
0025-12-31
, что, если мы укоротим форматирование даты Маркоса, даст нам «25», что является неправильным подсчетом возраста.
Ответ Брайана Денни правильный во всех этих крайних случаях. Его формула довольно умна:
SELECT DATE_FORMAT(reference, '%Y') - DATE_FORMAT(birthdate, '%Y') - (DATE_FORMAT(reference, '00-%m-%d') < DATE_FORMAT(birthdate, '00-%m-%d')) AS age
Первая часть вычисляет разницу в годах между двумя датами. Таким образом, если мы возьмем «2010» и «1984» в качестве ссылки и дату рождения соответственно, результатом будет «26». Затем вторая часть вычисляет, по существу, «встречаются ли месяц и день рождения после базового месяца и дня?» Если это произойдет, это «еще не произошло», поэтому нам нужно вычесть дополнительную 1 из разницы в году, чтобы компенсировать это. Об этом заботится результат сравнения <, который возвращает 1, если истина, и 0, если ложь. </p>
Итак, полные примеры:
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
Надеюсь, это прояснит ситуацию для людей!