Разница в месяцах между датами в MySQL



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



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

1237   18  

18 ответов:

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

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

посмотреть TIMESTAMPDIFF () функция в 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;

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

PERIOD_DIFF (P1,P2)

возвращает количество месяцев между периодами P1 и P2. P1 и P2 должны быть в формате YYMM или YYYYMM. Обратите внимание, что аргументы периода 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.

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

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

есть ли лучший способ? да. Не используйте временные метки MySQL. Помимо того, что они занимают 36 байт, с ними совсем не удобно работать. Я бы рекомендовал использовать Julian Date и Seconds from midnight для всех значений даты/времени. Они могут быть объединены, чтобы сформировать UnixDateTime. Если это хранится в DWORD (unsigned 4 Byte Integer), то даты вплоть до 2106 могут храниться в секундах с момента epoc, 01/01/1970 Dword max val = 4,294,967,295 - A DWORD может содержать 136 лет Секунды

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

преобразование в Julian и обратно может быть сделано очень быстро на хорошем языке. Используя указатели, у меня есть около 900 Clks (это также a преобразование из строки в целое число, конечно)

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

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

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

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

округлить до ближайшего целого числа.

рассмотрим эти примеры: 1 января - > 31 января: это 0 целых месяцев,и почти 1 месяц. 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 летами. Ответ Зейна, очевидно, более точен, но он слишком многословен на мой вкус.

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, которая даст вам разницу в формате даты yyyy-mm-dd.

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;

PERIOD_DIFF (функции)

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

код:

SELECT PERIOD_DIFF(200905,200811);

enter image description here

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

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

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

Comments

    Ничего не найдено.