Вопрос

Я хочу рассчитать количество месяцев между двумя полями даты и времени.

Есть ли лучший способ, чем получить временную метку Unix, разделить ее на 2 592 000 (секунд) и округлить в большую сторону в MySQL?

Это было полезно?

Решение

DATEDIFF Функция может дать вам количество дней между двумя датами. Что более точно, так как ... как вы определяете месяц? (28, 29, 30 или 31 день?)

Другие советы

Разница в месяцах между любыми двумя датами:

Я удивлен, что об этом еще не упомянули:

Взгляните на ТАЙМСТАМПДИФФ() функция в MySQL.

Это позволяет вам передать два TIMESTAMP или DATETIME ценности (или даже DATE поскольку MySQL будет автоматически конвертировать), а также единицу времени, на которой вы хотите основывать разницу.

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

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-04')
-- Outputs: 0

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-05')
-- Outputs: 1

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-15')
-- Outputs: 1

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-12-16')
-- Outputs: 7

По сути, он получает количество месяцев, прошедших с первой даты в списке параметров.Это решение автоматически компенсирует различное количество дней в каждом месяце (28,30,31), а также учитывает високосные годы — вам не нужно беспокоиться ни о чем из этого.


Разница в месяце с точностью:

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

SELECT 
  TIMESTAMPDIFF(MONTH, startdate, enddate) +
  DATEDIFF(
    enddate,
    startdate + INTERVAL
      TIMESTAMPDIFF(MONTH, startdate, enddate)
    MONTH
  ) /
  DATEDIFF(
    startdate + INTERVAL
      TIMESTAMPDIFF(MONTH, startdate, enddate) + 1
    MONTH,
    startdate + INTERVAL
      TIMESTAMPDIFF(MONTH, startdate, enddate)
    MONTH
  )

Где startdate и enddate ваши параметры даты, будь то из двух столбцов даты в таблице или как входные параметры из скрипта:

Примеры:

With startdate = '2012-05-05' AND enddate = '2012-05-27':
-- Outputs: 0.7097

With startdate = '2012-05-05' AND enddate = '2012-06-13':
-- Outputs: 1.2667

With startdate = '2012-02-27' AND enddate = '2012-06-02':
-- Outputs: 3.1935

PERIOD_DIFF рассчитывает месяцы между двумя датами.

Например, чтобы вычислить разницу между now () и временным столбцом в your_table:

select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;

Я также использую PERIODDIFF . Чтобы получить год и месяц даты, я использую функцию ВЫПИСКА :

  SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;

Я предпочитаю этот путь, потому что каждый на первый взгляд это поймет:

SELECT
    12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
    tab;

Как показывают многие ответы здесь, «правильный» ответ зависит именно от того, что вам нужно. В моем случае мне нужно округлить до ближайшего целого числа .

Рассмотрим эти примеры: 1 января - > 31 января: 0 целых месяцев и почти 1 месяц. 1 января - > 1 февраля? Это целый месяц, ровно 1 месяц.

Чтобы узнать количество целых (завершенных) месяцев, используйте:

SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31');  => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01');  => 1

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

SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1
SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1

Это с точностью до +/- 5 дней и для диапазонов более 1000 лет. Ответ Зейна, очевидно, более точный, но он мне слишком многословен.

Из руководства MySQL:

PERIOD_DIFF(P1,P2)

Возвращает количество месяцев между периодами P1 и P2.P1 и P2 должны быть в формате ГГММ или ГГГГММ.Обратите внимание, что аргументы периода P1 и P2 не являются значениями даты.

mysql> SELECT PERIOD_DIFF (200802,200703);-> 11

Итак, возможно, можно сделать что-то вроде этого:

Select period_diff(concat(year(d1),if(month(d1)<10,'0',''),month(d1)), concat(year(d2),if(month(d2)<10,'0',''),month(d2))) as months from your_table;

Где d1 и d2 — выражения даты.

Мне пришлось использовать операторы if(), чтобы убедиться, что месяцы представляют собой двузначное число, например 02, а не 2.

Есть ли лучший способ? да. Не используйте метки времени MySQL. Помимо того, что они занимают 36 байт, с ними совсем не удобно работать. Я бы порекомендовал использовать юлианские даты и секунды с полуночи для всех значений даты / времени. Они могут быть объединены, чтобы сформировать UnixDateTime. Если это сохранено в DWORD (4-байтовое целое число без знака), то даты вплоть до 2106 могут быть сохранены как секунды с момента epoc, 01.01.1970 DWORD max val = 4 294 967 295 - DWORD может содержать 136 лет секунд

Юлианские даты очень удобны при расчете дат Значения UNIXDateTime хороши для работы при расчете даты / времени Ни на что не годятся, поэтому я использую метки времени, когда мне нужен столбец, с которым я не буду много вычислять, но мне нужна быстрая индикация.

Преобразование в юлианский и обратно может быть выполнено очень быстро на хорошем языке. С помощью указателей у меня это примерно до 900 кликов (это тоже, конечно, преобразование из STRING в INTEGER)

Когда вы попадаете в серьезные приложения, которые используют информацию о дате / времени, например, финансовые рынки, юлианские даты де-факто.

Запрос будет выглядеть так:

select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..

Предоставляет количество календарных месяцев с момента создания метки даты в записи клиента, что позволяет MySQL самостоятельно выбирать месяц.

DROP FUNCTION IF EXISTS `calcula_edad` $
CREATE DEFINER=`root`@`localhost` FUNCTION `calcula_edad`(pFecha1 date, pFecha2 date, pTipo char(1)) RETURNS int(11)
Begin

  Declare vMeses int;
  Declare vEdad int;

  Set vMeses = period_diff( date_format( pFecha1, '%Y%m' ), date_format( pFecha2, '%Y%m' ) ) ;

  /* Si el dia de la fecha1 es menor al dia de fecha2, restar 1 mes */
  if day(pFecha1) < day(pFecha2) then
    Set vMeses = VMeses - 1;
  end if;

  if pTipo='A' then
    Set vEdad = vMeses div 12 ;
  else
    Set vEdad = vMeses ;
  end if ;
  Return vEdad;
End

select calcula_edad(curdate(),born_date,'M') --  for number of months between 2 dates

Выполните этот код, и он создаст функцию datedeifference, которая даст вам разницу в формате даты гггг-мм-дд.

DELIMITER $

CREATE FUNCTION datedifference(date1 DATE, date2 DATE) RETURNS DATE
NO SQL

BEGIN
    DECLARE dif DATE;
    IF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < 0    THEN
                SET dif=DATE_FORMAT(
                                        CONCAT(
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 , 
                                            '-',
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 , 
                                            '-',
                                            DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(DATE_SUB(date1, INTERVAL 1 MONTH)), '-', DAY(date2))))),
                                        '%Y-%m-%d');
    ELSEIF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < DAY(LAST_DAY(DATE_SUB(date1, INTERVAL 1 MONTH))) THEN
                SET dif=DATE_FORMAT(
                                        CONCAT(
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 , 
                                            '-',
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 , 
                                            '-',
                                            DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
                                        '%Y-%m-%d');
    ELSE
                SET dif=DATE_FORMAT(
                                        CONCAT(
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 , 
                                            '-',
                                            PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 , 
                                            '-',
                                            DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
                                        '%Y-%m-%d');
    END IF;

RETURN dif;
END $
DELIMITER;

Это зависит от того, как вы хотите определить количество месяцев. Ответьте на следующие вопросы: «Какая разница в месяцах: 15 февраля 2008 г. - 12 марта 2009 г.». Определяется ли оно четким числом # дней, которое зависит от високосных лет - какой это месяц или тот же день предыдущего месяца = 1 месяц.

Расчет для дней .

15 февраля - > 29 (високосный год) = 14 1 марта 2008 г. + 365 = 1 марта 2009 г. 1 марта - > 12 марта = 12 дней. 14 + 365 + 12 = 391 день. Итого = 391 день / (среднее число дней в месяце = 30) = 13,03333

Расчет месяцев .

15 февраля 2008 г. - 15 февраля 2009 г. = 12 15 февраля - > 12 марта = менее 1 месяца Итого = 12 месяцев или 13, если 15 февраля - 12 марта считается «прошедшим месяцем»

SELECT * 
FROM emp_salaryrevise_view 
WHERE curr_year Between '2008' AND '2009' 
    AND MNTH Between '12' AND '1'

Мне нужна была разница в месяц с точностью. Хотя решение Зейна Бина идет в правильном направлении, его второй и третий примеры дают неточные результаты. День в феврале, деленный на количество дней в феврале, не равен дню в мае, деленному на число дней в мае. Таким образом, второй пример должен вывести ((31-5 + 1) / 31 + 13/30 =) 1.3043, а третий пример ((29-27 + 1) / 29 + 2/30 + 3 =) 3.1701.

Я получил следующий запрос:

SELECT
    '2012-02-27' AS startdate,
    '2012-06-02' AS enddate,
    TIMESTAMPDIFF(DAY, (SELECT startdate), (SELECT enddate)) AS days,
    IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), 0, (TIMESTAMPDIFF(DAY, (SELECT startdate), LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY)) / DAY(LAST_DAY((SELECT startdate)))) AS period1,     
    TIMESTAMPDIFF(MONTH, LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY, LAST_DAY((SELECT enddate))) AS period2,
    IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), (SELECT days), DAY((SELECT enddate))) / DAY(LAST_DAY((SELECT enddate))) AS period3,
    (SELECT period1) + (SELECT period2) + (SELECT period3) AS months

Вы можете получить годы, месяцы и дни следующим образом:

SELECT 
username
,date_of_birth
,DATE_FORMAT(CURDATE(), '%Y') - DATE_FORMAT(date_of_birth, '%Y') - (DATE_FORMAT(CURDATE(), '00-%m-%d') < DATE_FORMAT(date_of_birth, '00-%m-%d')) AS years
,PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') ) AS months
,DATEDIFF(CURDATE(),date_of_birth) AS days
FROM users

Вы также можете попробовать это:

select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;

ИЛИ

select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;

Функция ПЕРИОД_РАЗ()

Один из способов — MySQL PERIOD_DIFF() возвращает разницу между двумя периодами.Периоды должны быть в одном формате, т.е.ГГГГММ или ГГММ.Следует отметить, что периоды не являются значениями дат.

Код:

SELECT PERIOD_DIFF(200905,200811);

enter image description here

Простой ответ с указанием начальной даты в виде ins_frm и конечной даты в виде ins_to

SELECT convert(TIMESTAMPDIFF(year, ins_frm, ins_to),UNSIGNED) as yrs,
       mod(TIMESTAMPDIFF(MONTH, ins_frm, ins_to),12) mnths
FROM table_name

Наслаждайтесь:)))

Попробуйте это

SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))

Этот запрос работал для меня:)

SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'

Он просто берет две даты и получает значения между ними.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top