18 ответов:
The DATEDIFF
месяц-разница между любыми двумя датами:
я удивлен, что это еще не было упомянуто:
посмотреть 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;
этот запрос работал для меня:)
SELECT * FROM tbl_purchase_receipt WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'Он просто принимает две даты и извлекает значения между ними.

Comments