Вставка записи между двумя таблицами (выбор, когда рассчитать возраст)

Ниже приведен мой запрос sql для cron, в котором я пытаюсь сохранить записи из одной таблицы в другую таблицу. Мне просто нужна одна модификация, которую я не мог бы сделать в моем поле i_age, возраст должен быть сохранен в db, но если ноль начинается с предыдущей таблицы, тогда формула расчета возраста не применяется, и она сохраняет только нулевое поле i_age, любезно сообщите мне, как я могу это сделать,

спасибо,

INSERT IGNORE into z_census ( i_age)
            SELECT  IF((i_age = 0), i_age, FLOOR(DATEDIFF(DATE(NOW()),DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND))/365.25) )
            FROM users

Ответ 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)

Это даст более точный результат, но будет более уродливым, чем другое выражение, которое возвращает почти эквивалентный результат.