Я хочу рассчитать количество месяцев между двумя полями даты и времени.
Есть ли лучший способ, чем получить временную метку unix и разделить на 2 592 000 (секунд) и округлить в MySQL?
mysql
date
datediff
date-arithmetic
Дэррил Хайн
источник
источник
PERIODDIFF
просто принимает значение ГГГГММ, поэтому, если вы сами не учитываете дни перед передачей значений ГГГГММ, тогда все, что вы вычисляете, - это количество месяцев, округленное до ближайшего месяца, если число месяцев меньше целого. См. Ответ Зейна ниже.PERIODDIFF
комментарий так много положительных отзывов ? Perioddiff не принимает значения дня, поэтому вы вычисляете количество месяцев с округлением до ближайшего месяца, если число месяцев меньше целогоРазница в месяцах между любыми двумя датами:
Я удивлен, что об этом еще не упомянули:
Взгляните на функцию 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
источник
PERIODDIFF
комментарий к выбранному ответу оченьPERIOD_DIFF вычисляет месяцы между двумя датами.
Например, чтобы вычислить разницу между now () и столбцом времени в your_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
источник
Использую также PERIODDIFF . Чтобы получить год и месяц даты, я использую функцию EXTRACT :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
источник
DATE_FORMAT
метод использует на 50% меньше времени , спасибо! +1SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(time, "%Y%m%d"))) AS months FROM your_table;
PERIOD_DIFF
не принимает значения дня, поэтому вы вычисляете количество месяцев с округлением до ближайшего месяца, если количество месяцев меньше целого. Вы должны отредактировать свой ответ, чтобы прояснить это.Как показывают многие из приведенных здесь ответов, «правильный» ответ зависит от того, что именно вам нужно. В моем случае мне нужно округлить до ближайшего целого числа .
Рассмотрим эти примеры: 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:
Так что можно сделать что-то вроде этого:
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 байт, работать с ними совсем не удобно. Я бы рекомендовал использовать юлианские даты и секунды с полуночи для всех значений даты и времени. Их можно объединить в UnixDateTime. Если это сохранено в DWORD (беззнаковое 4-байтовое целое число), тогда даты вплоть до 2106 могут быть сохранены в секундах с момента epoc, 01.01.1970 DWORD max val = 4,294,967,295 - DWORD может содержать 136 лет секунд
Юлианские даты очень удобны для работы при вычислении даты. Значения UNIXDateTime удобны для работы при вычислении даты и времени. На них также не стоит смотреть, поэтому я использую временные метки, когда мне нужен столбец, который я не буду выполнять много вычислений. с, но мне нужна краткая информация.
Преобразование в юлианский и обратно может быть выполнено очень быстро на хорошем языке. Используя указатели, у меня это примерно до 900 Clks (это также преобразование из 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, которая даст вам разницу в формате даты 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 марта 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
источник
Функция PERIOD_DIFF ()
Один из способов - MySQL PERIOD_DIFF () возвращает разницу между двумя периодами. Точки должны быть в одном формате, например ГГГГММ или ГГММ. Следует отметить, что периоды не являются значениями даты.
Код:
SELECT PERIOD_DIFF(200905,200811);
источник
Вы можете получить годы, месяцы и дни следующим образом:
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;
источник
Простой ответ с указанием даты начала как 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'
Он просто берет две даты и извлекает значения между ними.
источник