Ответ 1
Это эквивалентно выражению в вашем запросе, которое вычисляет "возраст" (в целых) годах:
FLOOR(DATEDIFF(DATE(NOW()),
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
)/365.25)
Это выражение действительно имеет вид:
FLOOR(DATEDIFF(DATE(NOW()), dob )/365.25)
где dob
- это значение DATE, которое представляет собой дату рождения пользователя. Вывод dob
с помощью этого выражения:
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
(Это основано на некоторых предположениях, как указано ниже.)
Альтернатива:
Этот расчет возвращает почти тот же результат, но на самом деле более точный:
IF(YEAR(NOW())<=YEAR( dob ), 0,
YEAR(NOW())-YEAR( dob ) /* yeardiff and subtract 1 if now is before birthday */
- (MONTH(NOW())<MONTH( dob ) OR
(MONTH(NOW())=MONTH( dob ) AND DAY(NOW())<DAY( dob )))
)
ПРИМЕЧАНИЕ. Опять же, в этом выражении dob
представляет фактическое значение DATE MySQL, а не целое число секунд. Чтобы использовать это, вы замените все пять вхождений dob
следующим выражением:
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
Подробнее:
Похоже, что тип данных столбца users.i_dob
представляет дату как целое число секунд с полуночи 1 января 1970 года. (Учитывая, что это похоже на "работу" для DOB после 1970 года, но не раньше. это, скорее всего, (подписанный) INT
или BIGINT
. (Возможно, это столбец символов, и значение неявно преобразуется в числовое. Столбец TIMESTAMP не позволяет хранить значения даты раньше, чем 1 января, 1970.)
(Имея информацию о фактических типах данных соответствующих столбцов, вы поможете некоторым.)
Учитывая, что ведущее "i_" в имени столбца, мы собираемся идти вперед в предположении, что столбец users.i_dob
определяется как INT
и представляет количество секунд с полуночи 1 января 1970 UTC.
Это дает эффективный диапазон значений "dob", которые могут быть представлены ок. '1901-12-14' до '2038-01-19'
Похоже, что этот запрос:
SELECT DISTINCT users.id
, users.v_first_name
, users.v_last_name
, FLOOR((TO_DAYS(NOW())- TO_DAYS(FROM_UNIXTIME(users.i_dob))) / 365.25)
FROM users
пытается рассчитать возраст пользователей в годах.
Эта функция FROM_UNIXTIME
работает с значениями TIMESTAMP, поэтому она не будет "работать" для значений до 1 января 1970 года.
Чтобы получить фактическое значение DATETIME, представленное i_dob, мы можем использовать функцию DATE_ADD
.
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
Чтобы получить количество дней между этим значением DATETIME и текущей датой, мы используем функцию DATEDIFF
:
DATEDIFF(NOW(),DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND))
(Функция DATEDIFF игнорирует компоненты времени и работает только с частью даты, что наиболее вероятно, что вы хотите. Расчет в вашем запросе включает часть времени, которая добавляет немного неряшливости.)
Из числа дней, похоже, вы рассчитываете годы, делясь на количество дней в году, там крошечная битка там, когда NOW() находится в течение дня своего дня рождения... но я "Не буду беспокоиться, демонстрируя это здесь.)
Итак, я думаю, что это должно быть достаточно близко для вас,
= FLOOR(DATEDIFF(DATE(NOW()),
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
)/365.25)
Более точный расчет "возраста" людей действительно должен сравнивать год, месяц и день. Если нас интересует только непредсказуемый возраст, что-то вроде этого будет работать:
IF(YEAR(NOW())<=YEAR( dob ), 0,
YEAR(NOW())-YEAR( dob ) /* yeardiff and subtract 1 if now is before birthday */
- (MONTH(NOW())<MONTH( dob ) OR
(MONTH(NOW())=MONTH( dob ) AND DAY(NOW())<DAY( dob )))
)
ПРИМЕЧАНИЕ: dob
в этом выражении представляет значение MySQL DATE
, представляющее "dob", а не целое число секунд.
ПРИМЕЧАНИЕ: это выражение вернет только неотрицательные значения; он никогда не вернет отрицательный возраст.
Я признаю, что это выглядит немного сложнее, но все, что действительно делает, это проверка того, что возраст не менее 1 года и в противном случае вычитает годы, а затем с помощью условного теста (который возвращает логическое значение, мы интерпретируем как целое число 1 или 0), чтобы изменить разницу на 1 год, когда текущий месяц и день до месяца и дня дня рождения.)
В вашем случае, чтобы использовать это, вам нужно будет заменить все пять вхождений dob
в этом выражении выражением, которое получает значение dob DATE
из целого числа, то есть
dob = DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
Это даст более точный результат, но будет более уродливым, чем другое выражение, которое возвращает почти эквивалентный результат.