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?

Foi útil?

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;

PERIOD_DIFF () function

Uma das formas é o MySQL PERIOD_DIFF () retorna a diferença entre os dois períodos. Períodos deve ser no mesmo formato ou seja YYYYMM ou YYMM. É de notar que os períodos não são valores de data.

Código:

SELECT PERIOD_DIFF(200905,200811);

enter descrição da imagem aqui

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top