Estou tentando calcular o número de meses entre 2 campos de data e hora.
Existe uma maneira melhor do que obter o carimbo de data / hora Unix e dividir por 2 592 000 (segundos) e arredondar dentro do MySQL?
mysql
date
datediff
date-arithmetic
Darryl Hein
fonte
fonte
PERIODDIFF
simplesmente assume um valor AAAAMM, portanto, a menos que você mesmo considere os dias antes de passar os valores AAAAMM, tudo o que você está calculando é o número de meses, arredondado para o mês mais próximo se houver menos do que um número inteiro de meses. Veja a resposta de Zane abaixo.PERIODDIFF
comentário? Perioddiff não leva valores de dias, então você está calculando o número de meses arredondado para o mês mais próximo se houver menos do que um número inteiro de mesesDiferença de mês entre quaisquer duas datas:
Estou surpreso que ainda não tenha sido mencionado:
Dê uma olhada na função TIMESTAMPDIFF () no MySQL.
O que isso permite que você faça é passar dois valores
TIMESTAMP
ouDATETIME
(ou mesmoDATE
que o MySQL se converta automaticamente), bem como a unidade de tempo na qual deseja basear sua diferença.Você pode especificar
MONTH
como 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 leva em consideração os anos bissextos - você não precisa se preocupar com nada disso.
Diferença de mês com precisão:
É um pouco mais complicado se você quiser introduzir a precisão decimal no número de meses decorridos, mas aqui está como você pode fazer isso:
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
eenddate
estão seus parâmetros de data, seja 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
fonte
PERIODDIFF
comentário sobre a resposta selecionada são muitoPERIOD_DIFF calcula meses entre duas datas.
Por exemplo, para calcular a diferença entre now () e uma coluna de tempo em sua_tabela:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
fonte
Eu uso também PERIODDIFF . Para obter o ano e o mês da data, uso a função EXTRACT :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
fonte
DATE_FORMAT
método, obrigado! +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
não leva valores de dia, então você está calculando o número de meses arredondado para o mês mais próximo se houver menos de um número inteiro de meses. Você deve editar sua resposta para deixar isso claro.Como muitas das respostas aqui mostram, a resposta 'certa' depende exatamente do que você precisa. No meu caso, preciso arredondar para o número inteiro mais próximo .
Considere estes exemplos: 1º de janeiro -> 31 de janeiro: São 0 meses inteiros e quase 1 mês de duração. 1 ° de janeiro -> 1 ° de fevereiro? É 1 mês inteiro e exatamente 1 mês de duração.
Para obter o número de meses inteiros (completos) , use:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0 SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
Para obter uma duração arredondada em meses, você pode 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
A precisão é de +/- 5 dias e para intervalos de mais de 1000 anos. A resposta de Zane é obviamente mais precisa, mas é muito prolixa para o meu gosto.
fonte
Do manual do MySQL:
Portanto, pode ser possível fazer algo assim:
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.
Tive que usar as instruções if () para ter certeza de que os meses eram um número de dois dígitos como 02 em vez de 2.
fonte
Prefiro assim, porque todo mundo vai entender claramente à primeira vista:
SELECT 12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months FROM tab;
fonte
Existe uma maneira melhor? sim. Não use carimbos de data / hora do MySQL. Além do fato de que eles ocupam 36 bytes, eles não são nada convenientes para trabalhar. Eu recomendaria usar a data juliana e os segundos a partir da meia-noite para todos os valores de data / hora. Eles podem ser combinados para formar um UnixDateTime. Se for armazenado em um DWORD (inteiro não assinado de 4 bytes), as datas até 2.106 podem ser armazenadas como segundos desde o período, 01/01/1970 DWORD max val = 4.294.967.295 - Um DWORD pode conter 136 anos de segundos
É muito bom trabalhar com datas julianas ao fazer cálculos de data. Valores UNIXDateTime são bons para trabalhar ao fazer cálculos de data / hora. Também não são bons de olhar, então eu uso os timestamps quando preciso de uma coluna que não irei fazer muitos cálculos com, mas eu quero uma indicação rápida.
Converter para Juliano e vice-versa pode ser feito muito rapidamente em um bom idioma. Usando ponteiros, baixei para cerca de 900 Clks (também é uma conversão de STRING para INTEGER, é claro)
Quando você entra em aplicativos sérios que usam informações de data / hora como, por exemplo, os mercados financeiros, as datas julianas são de fato.
fonte
A consulta será como:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Fornece vários meses do calendário desde a data de criação criada em um registro do cliente, permitindo que o MySQL faça a seleção do mês internamente.
fonte
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
fonte
Execute este código e ele criará uma função datedeifference 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;
fonte
Isso depende de como você deseja que o número de meses seja definido. Responda a estas perguntas: 'Qual é a diferença em meses: 15 de fevereiro de 2008 - 12 de março de 2009'. É definido por um número claro de dias que depende dos anos bissextos - em que mês se trata, ou mesmo dia do mês anterior = 1 mês.
Um cálculo para dias :
15 de fevereiro -> 29 (ano bissexto) = 14 1º de março de 2008 + 365 = 1º de março de 2009. 1º de março -> 12 de março = 12 dias. 14 + 365 + 12 = 391 dias. Total = 391 dias / (média de dias no mês = 30) = 13,03333
Um cálculo de meses :
15 de fevereiro de 2008 - 15 de fevereiro de 2009 = 12 de 15 de fevereiro -> 12 de março = menos de 1 mês Total = 12 meses, ou 13 se 15 de fevereiro - 12 de março for considerado 'o mês anterior'
fonte
SELECT * FROM emp_salaryrevise_view WHERE curr_year Between '2008' AND '2009' AND MNTH Between '12' AND '1'
fonte
Eu precisava da diferença do mês com precisão. Embora a solução de Zane Bien esteja na direção certa, seu segundo e terceiro exemplos fornecem 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. Portanto, o segundo exemplo deve gerar ((31-5 + 1) / 31 + 13/30 =) 1,3043 e o terceiro exemplo ((29-27 + 1) / 29 + 2/30 + 3 =) 3,1701.
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
fonte
Função PERIOD_DIFF ()
Uma das maneiras é MySQL PERIOD_DIFF () retorna a diferença entre dois períodos. Os pontos devem estar no mesmo formato, ou seja, AAAAM ou AAAM. Deve-se notar que os períodos não são valores de data.
Código:
SELECT PERIOD_DIFF(200905,200811);
fonte
Você pode obter anos, meses e dias desta forma:
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
fonte
Você também pode tentar isso:
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;
fonte
Resposta simples com data de início ins_frm e data de término 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
Apreciar :)))
fonte
Tente isto
SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))
fonte
Esta consulta funcionou para mim :)
SELECT * FROM tbl_purchase_receipt WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
Ele simplesmente pega duas datas e recupera os valores entre elas.
fonte