Я хочу розрахувати кількість місяців між двома полями дати.
Чи є кращий спосіб, ніж отримання мітки часу unix та ділення на 2 592 000 (секунди) та округлення в MySQL?
Я хочу розрахувати кількість місяців між двома полями дати.
Чи є кращий спосіб, ніж отримання мітки часу unix та ділення на 2 592 000 (секунди) та округлення в MySQL?
Відповіді:
Функція DATEDIFF може дати вам кількість днів між двома датами. Що точніше, оскільки ... як ви визначаєте місяць? (28, 29, 30 або 31 день?)
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 () та часовим стовпцем у вашій_таблиці:
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
метод, дякую! +1
SELECT 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 цілий місяць і рівно 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 повинні мати формат YYMM або YYYYMM. Зверніть увагу, що аргументи періоду P1 та P2 не є значеннями дати.
mysql> ВИБЕРІТЬ ПЕРІОД_ДІФФ (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.
Я віддаю перевагу цьому шляху, тому що evryone це зрозуміє з першого погляду:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
Чи є кращий спосіб? так. Не використовуйте мітки часу MySQL. Окрім того, що вони займають 36 байт, з ними зовсім не зручно працювати. Я б рекомендував використовувати дату і секунди Джуліана з півночі для всіх значень дати / часу. Вони можуть бути об'єднані, щоб сформувати UnixDateTime. Якщо це зберігається в DWORD (4-байтове ціле число без підпису), то дати аж до 2106 можуть зберігатися як секунди з епохи, 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
Виконайте цей код, і він створить функцію dateeifference, яка дасть вам різницю у форматі дати рррр-мм-дд.
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
Ви можете отримати роки, місяці та дні таким чином:
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'
Просто потрібно дві дати і отримує значення між ними.