A diferença em meses entre as datas no MySQL
-
08-07-2019 - |
Pergunta
Eu estou olhando para calcular o número de meses entre campos de tempo 2 de data.
Existe uma maneira melhor do que começar o timestamp unix e metade por 2 592 000 (segundos) e arredondamento whithin MySQL?
Solução
O DATEDIFF função pode dar-lhe o número de dias entre duas datas. Que é mais preciso, uma vez que ... como você define um mês? (28, 29, 30 ou 31 dias?)
Outras dicas
Mês-diferença entre quaisquer dadas duas datas:
Estou surpreso este ainda não foi mencionado:
Tenha um olhar para o < strong> TIMESTAMPDIFF () função> no MySQL.
O que isto permite-lhe fazer é passar em dois valores TIMESTAMP
ou DATETIME
(ou mesmo DATE
como MySQL vontade auto-convertido), bem como a unidade de tempo que você deseja basear a sua diferença diante.
Você pode especificar MONTH
como a unidade no primeiro parâmetro:
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
É basicamente obtém o número de meses decorridos desde a primeira data na lista de parâmetros. Esta solução compensa automaticamente a quantidade variável de dias em cada mês (28,30,31), bem como tendo em conta os anos bissextos -. Você não precisa se preocupar com nada disso
Mês-diferença com precisão:
É um pouco mais complicado se você quer introduzir precisão decimal do número de meses decorridos, mas aqui está como você pode fazê-lo:
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
)
Onde startdate
e enddate
são seus parâmetros de data, quer seja a partir de duas colunas de data em uma tabela ou como parâmetros de entrada de um script:
Exemplos:
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 Calcula meses entre duas datas.
Por exemplo, para calcular a diferença entre o momento () e uma coluna de tempo em your_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
Eu uso também PERIODDIFF . Para obter o ano eo mês da data, eu uso a função EXTRATO :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
Eu prefiro assim, porque todo mundo vai entender claramente à primeira vista:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
Como muitas das respostas aqui mostram, a resposta 'certa' depende exatamente o que você precisa. No meu caso, eu preciso arredondar para o número inteiro mais próximo .
Considere estes exemplos: 01 de janeiro -> 31 de janeiro: É 0 inteiras meses, e quase um mês longo. 01 de janeiro -> 01 de fevereiro? É 1 mês inteiro, e exatamente um mês longo.
Para obter o número de inteira (completa) meses, use:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
Para obter um arredondada duração em meses, você poderia usar:
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
Este é preciso para +/- 5 dias e para intervalos de mais de 1000 anos. A resposta de Zane é, obviamente, mais preciso, mas é muito detalhado para o meu gosto.
A partir do MySQL manual:
PERIOD_DIFF (P1, P2)
Retorna o número de meses entre períodos P1 e P2. P1 e P2 deve estar na YYMM formato ou YYYYMM. Note-se que os argumentos período P1 e P2 não são valores de data.
mysql> SELECIONA PERIOD_DIFF (200802,200703); -> 11
Assim, pode ser possível fazer algo parecido com isto:
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;
Onde D1 e D2 são as expressões de data.
Eu tive que usar as declarações if () para se certificar de que os meses era um número de dois dígitos, como 02, em vez de 2.
Existe uma maneira melhor? sim. Não use MySQL Timestamps. Além do fato de que eles ocupam 36 bytes, eles não são de todo conveniente para trabalhar. Eu recomendaria usando Julian Data e Segundos a partir da meia-noite para todos os valores de data / hora. Estes podem ser combinados para formar um UnixDateTime. Se este é armazenado em um DWORD (sem assinatura 4 Byte Integer), em seguida, datas todo o caminho até a 2106 podem ser armazenados como segundos desde epoc, 01/01/1970 DWORD máximo val = 4294967295 - A DWORD pode conter 136 anos de segundos
Datas Julian são muito bom trabalhar com ao fazer cálculos de data valores UNIXDateTime são bons para trabalhar com ao fazer Data / cálculos Tempo Nem são bons para olhar, então eu uso o Timestamps quando eu preciso de uma coluna que eu não vou estar fazendo muito cálculo com, mas eu quero uma indicação at-a-glance.
A conversão para Julian e volta pode ser feito muito rapidamente em uma linguagem bem. Usando ponteiros eu tê-lo para baixo para cerca de 900 Clks (Esta é também uma conversão de uma string em um inteiro, é claro)
Quando você chegar em aplicações sérias de que o uso de Data / Hora informações como, por exemplo, os mercados financeiros, as datas Julian são de facto.
A consulta será como:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Dá um número de meses de calendário desde o datestamp criado em um registro do cliente, deixando MySQL fazer a seleção mês internamente.
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
Executar este código e ele irá criar uma datedeifference função que lhe dará a diferença no formato de data aaaa-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;
Isso depende de como você deseja que o Número de meses a ser definido. Responder a esta pergunta: 'Qual é a diferença em meses: 15 de fevereiro de 2008 - 12 de março de 2009'. É definida pelo clear cut número de dias que depende anos- salto que mês é, ou mesmo dia do mês anterior = 1 mês.
Um cálculo para Days :
15 de fevereiro -> 29 (ano bissexto) = 14 01 março de 2008 + 365 = 1 de março de 2009. 01 de março -> 12 março = 12 dias. 14 + 365 + 12 = 391 dias. Total = 391 dias / (dias avg no mês = 30) = 13,03333
Um cálculo de meses :
15 fevereiro de 2008 - 15 de fevereiro de 2009 = 12 15 Fev -> Mar 12 = menos de 1 mês Total = 12 meses, ou 13 se 15 fevereiro - 12 março é considerado 'o passado mês'
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
Eu precisava meses de diferença com precisão. Embora a solução de Zane Bien é na direção certa, seus segundo e terceiro exemplos dão resultados imprecisos. Um dia em fevereiro, dividido pelo número de dias em fevereiro não é igual a um dia em Maio, dividido pelo número de dias em maio. Assim, o segundo exemplo deve saída ((31-5 + 1) / 31 + 13/30 =) 1,3043 e o terceiro exemplo ((29-27 + 1) / + 29 30/02 + 3 =) 3,1701.
Eu acabei com a seguinte consulta:
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
Você pode obter anos, meses e dias desta maneira:
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
Você também pode tentar o seguinte:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
ou
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
Simples resposta dada data de início como a data ins_frm e fim como 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
Enjoy:)))
Tente este
SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))
Esta consulta funcionou para mim:)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
Ele simplesmente tomar duas datas e recupera os valores entre eles.