Translate

quarta-feira, 13 de novembro de 2013

Mysql - diferença entre datas

Neste post vamos apresentar 4 exemplos de como calcular a diferença entre datas.

Caso tenha interesse, faça o download dos scripts no Google Drive ou veja no GitHub.

Para calcular a diferença entre duas datas, em dias, utilizamos a função "DATEDIFF". Esta função é utilizada no 1º e 2º exemplos.

DATEDIFF (data_final, data_inicial)

Também podemos utilizar a função "TIMESTAMPDIFF" para calcular a diferença entre datas. Esta função é utilizada no 3º e 4º exemplos.

TIMESTAMPDIFF (unidade_de_tempo, data_inicial, data_final)

A unidade de tempo pode ser:
  • YEAR: retorna a quantidade de anos completos;
  • MONTH: retorna a quantidade de meses completos;
  • DAY: retorna a quantidade de dias completos;
  • HOUR: retorna a quantidade de horas completas;
  • MINUTE: retorna a quantidade de minutos completos;
  • SECOND: retorna a quantidade de segundos completos;
  • QUARTER: retorna a quantidade de trimestres completos;

1º Exemplo

Cenário: em uma imobiliária, um funcionário precisa fazer um levantamento de quantos dias são necessários para alugar os imóveis. Para fazer este cálculo vamos utilizar a tabela "tb_locacao". Esta tabela possui três colunas:

  • imovel_id: número de identificação do imóvel;
  • data_oferta: data de início da oferta do imóvel;
  • data_locacao: a data em que o imóvel foi alugado;
Veja a imagem da tabela "tb_locacao":



Solução: temos que calcular a diferença entre as colunas "data_locação" e "data_oferta".

Para calcularmos a diferença em dias executamos a sentença abaixo:

SELECT
imovel_id,
data_oferta,
data_locacao,
/*Calculo da diferença entre a data da locação e a data de oferta*/
DATEDIFF (data_locacao, data_oferta) AS quantidade_dias
FROM tb_locacao;

Após executarmos a sentença acima, teremos o resultado exibido na tabela abaixo:


Observação: caso seja necessário incluir o primeiro dia na contagem dos dias, acrescente um dia ao calculo de diferença de datas, veja a sentença a seguir:

SELECT
imovel_id,
data_oferta,
data_locacao,
DATEDIFF (data_locacao, data_oferta) AS quantidade_dias,
/*Calculo da diferença entre a data da locação e a data de oferta, levando em consideração o primeiro dia*/
ABS(DATEDIFF (data_locacao, data_oferta)) + 1 AS quantidade_dias_primeiro_dia 
FROM tb_locacao;

Após executarmos a sentença acima, teremos o resultado exibido na tabela a seguir:




Perceba que utilizamos a função "ABS" antes de somar um 1 dia a diferença. 
A função ABS, garante que não seja retornado resultado da diferença negativo. 


Quando o resultado da diferença é negativo?

Se a data final for menor que a data inicial.

Hipótese:
Se o imóvel que possui id igual a 1 tivesse: 
  • a data_oferta     =  2013-08-17
  • a data_locacao  =  2013-08-01

O resultado seria -17  ao invés 17


2º Exemplo

Cenário: uma loja virtual vai oferecer uma oferta especial, aos clientes que estão cadastrados a mais de 90 dias no seu site. Para fazer este cálculo vamos utilizar a tabela "tb_cadastro". Esta tabela possui duas colunas:

  • cliente_id: número de identificação do cliente;
  • data_cadastro: data de cadastro do cliente;
Veja a imagem da tabela "tb_cadastro":


Solução: temos que calcular a diferença entre o dia atual (hoje) e a coluna data_cadastro.
Antes de efetuarmos o cálculo devemos saber como retornar o dia atual.
Para retorna o dia atual utilizamos a função:

CURRENT_DATE

OU

CURDATE()

Para exibirmos o dia atual execute a sentença abaixo (quando executei esta sentença o dia era 13/11/2013):

SELECT CURRENT_DATE;

OU

SELECT CURDATE()


Agora que já conhecemos a função que calcula o dia atual (hoje), vamos executar a sentença para verificar os clientes que estão cadastrados a mais de 90 dias.

SELECT
cliente_id,
data_cadastro,
/*calcula a diferença em dias completos*/
DATEDIFF(CURDATE(), data_cadastro) AS quantidade_dias
FROM tb_cadastro
/*filtra somente os clientes que são cadastrados há mais que 90 dias*/
WHERE DATEDIFF(CURDATE(), data_cadastro) > 90;

Após executarmos a sentença acima, filtramos os clientes que estão cadastrados a mais de 90 dias. Veja a imagem na tabela abaixo:

Observações
Se você colocar a data inicial antes da data final, como está exibido abaixo, a diferença será negativa.

DATEDIFF(data_inicial, data_final)

3º Exemplo

Cenário: uma fábrica quer calcular o periodo de utilização da seus equipamentos, em anos. Para fazer este cálculo vamos utilizar a tabela "tb_equipamento". Esta tabela possui duas colunas:
  • equipamento_id: número de identificação do equipamento;
  • data_inicio: data de inicio da utilização do equipamento;
  • data_encerramento: data de encerramento da utilização do equipamento;
Veja a imagem da tabela "tb_equipamento":


Solução: temos que calcular a diferença entre a coluna data_encerramento e a coluna data_inicio.

SELECT
equipamento_id,
data_inicio,
data_encerramento,
/*calcula a diferença em anos completos*/
TIMESTAMPDIFF(YEAR , data_inicio, data_encerramento) AS periodo_anos
FROM tb_equipamento;




4º Exemplo

Cenário: vamos calcular o período dos equipamentos mas agora em anos, meses, dias, horas, minutos e segundos.
Veja a imagem da tabela "tb_equipamento":


Para calcularmos o período, executamos a sentença abaixo:

SELECT 
data_inicio,
data_encerramento,
/**
 *Calcular a diferença em anos.
 */
TIMESTAMPDIFF(YEAR, data_inicio, data_encerramento) AS anos ,
/**
 *Calcular a diferença em meses.
 *Não vão ser contados os meses que já entraram na contagem dos anos completos.  
 */
TIMESTAMPDIFF
(
MONTH, 
data_inicio + INTERVAL TIMESTAMPDIFF(YEAR,  data_inicio, data_encerramento) YEAR , 
data_encerramento
) AS meses,
/**
 *Calcular a diferença em dias.
 *Não vão ser contados os dias que já entraram na contagem dos meses completos.  
 */
TIMESTAMPDIFF
(
DAY
data_inicio + INTERVAL TIMESTAMPDIFF(MONTH, data_inicio, data_encerramento) MONTH
data_encerramento
) AS dias ,
/**
 *Calcular a diferença em horas.
 *Não vão ser contadas as horas que já entraram na contagem dos dias completos.  
 */
TIMESTAMPDIFF
(
HOUR
data_inicio + INTERVAL TIMESTAMPDIFF(DAY,  data_inicio, data_encerramento) DAY
data_encerramento
) AS horas,
/**
 *Calcular a diferença em minutos.
 *Não vão ser contados os minutos que já entraram na contagem das horas completas.  
 */
TIMESTAMPDIFF
(
MINUTE
data_inicio + INTERVAL TIMESTAMPDIFF(HOUR,  data_inicio, data_encerramento) HOUR
data_encerramento
) AS minutos,
/**
 *Calcular a diferença em segundos.
 *Não vão ser contados os segundo que já entraram na contagem dos minutos completos.  
 */
TIMESTAMPDIFF
(
SECOND
data_inicio + INTERVAL TIMESTAMPDIFF(MINUTE,  data_inicio, data_encerramento) MINUTE, 
data_encerramento
) AS segundos
FROM tb_equipamento;

Após a execução da sentença temos o resultado a seguir:










Em breve postarei mais exemplos de função com data.

11 comentários:

  1. cara, muito show de bola.
    soh uma duvida, quando estou calculando a diferente de datas de diferentes tabelas, como eu faco?

    ResponderExcluir
    Respostas
    1. --Exemplo: se eu tenho duas tabelas:

      /*
      tabela_a:

      *coluna id = armazena a identificação

      *coluna data_inicial = armazena a data inicial

      *Foi cria uma chave primária chamada pk_id PARA A COLULA "id" para que não fossem
      cadastrados id repetidos

      *Veja abaixo o script de criação da tabela_a
      */
      CREATE TABLE tabela_a
      (
      id integer,
      data_inicial date,
      CONSTRAINT pk_id PRIMARY KEY (id)
      );

      /*
      tabela_b:

      *coluna id = armazena a identificação

      *coluna data_final = armazena a data final

      *Foi cria uma chave estrangeira chamada fk_id para a colula "id".
      Os registro somente serão inseridos na coluna "id" da "tabela_b", se já estiverem cadastrados na "tabela_a")

      *Veja abaixo o script de criação da tabela_b
      */
      CREATE TABLE tabela_b
      (
      id integer,
      data_final date,
      CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES tabela_a(id)
      );


      INSERT INTO tabela_a VALUES(1,'2015-04-14');
      INSERT INTO tabela_a VALUES(2,'2015-04-16');
      INSERT INTO tabela_a VALUES(3,'2015-04-24');
      INSERT INTO tabela_a VALUES(4,'2015-03-20');
      INSERT INTO tabela_a VALUES(5,'2015-03-22');
      INSERT INTO tabela_a VALUES(6,'2015-03-27');
      INSERT INTO tabela_a VALUES(7,'2015-03-28');
      INSERT INTO tabela_a VALUES(8,'2015-03-18');

      INSERT INTO tabela_b VALUES(1,'2015-10-24');
      INSERT INTO tabela_b VALUES(2,'2015-10-19');
      INSERT INTO tabela_b VALUES(3,'2015-10-13');
      INSERT INTO tabela_b VALUES(4,'2015-11-27');
      INSERT INTO tabela_b VALUES(5,'2015-11-29');
      INSERT INTO tabela_b VALUES(6,'2015-11-30');



      --Listar a tabela tabela_a
      SELECT * FROM tabela_a;

      id | data_inicial
      ----+--------------
      1 | 2015-04-14
      2 | 2015-04-16
      3 | 2015-04-24
      4 | 2015-03-20
      5 | 2015-03-22
      6 | 2015-03-27
      7 | 2015-03-28
      8 | 2015-03-18


      --Listar a tabela tabela_b
      SELECT * FROM tabela_b;

      id | data_final
      ---+------------
      1 | 2015-10-24
      2 | 2015-10-19
      3 | 2015-10-13
      4 | 2015-11-27
      5 | 2015-11-29
      6 | 2015-11-30

      /*
      Use o comando JOIN para parear as tabelas e comparar datas da tabela_a e da tabela_b que tenham o mesmo id
      (neste caso os id 1,2,3,4,5,6 estão tanto na tabela_a quanto na tabela_b)
      */
      SELECT
      tabela_a.id,
      tabela_a.data_inicial,
      tabela_b.data_final,
      DATEDIFF (tabela_b.data_final, tabela_a.data_inicial) AS quantidade_dias
      FROM tabela_a
      INNER JOIN tabela_b ON tabela_a.id = tabela_b.id;

      id | data_inicial | data_final | quantidade_dias
      ----+--------------+------------+----------------
      1 | 2015-04-14 | 2015-10-24 | 193
      2 | 2015-04-16 | 2015-10-19 | 186
      3 | 2015-04-24 | 2015-10-13 | 172
      4 | 2015-03-20 | 2015-11-27 | 252
      5 | 2015-03-22 | 2015-11-29 | 252
      6 | 2015-03-27 | 2015-11-30 | 248



      /*
      Use o comando LEFT JOIN para parear as tabelas, exibe todos os id da tabela_a mesmo que não estejam na tabela_b
      (neste caso os id 7,8 estão na tabela_a mas não estão na tabela_b)
      */
      SELECT
      tabela_a.id,
      tabela_a.data_inicial,
      tabela_b.data_final,
      DATEDIFF (tabela_b.data_final, tabela_a.data_inicial) AS quantidade_dias
      FROM tabela_a
      LEFT JOIN tabela_b ON tabela_a.id = tabela_b.id;

      id | data_inicial | data_final | quantidade_dias
      ----+--------------+------------+-----------------
      1 | 2015-04-14 | 2015-10-24 | 193
      2 | 2015-04-16 | 2015-10-19 | 186
      3 | 2015-04-24 | 2015-10-13 | 172
      4 | 2015-03-20 | 2015-11-27 | 252
      5 | 2015-03-22 | 2015-11-29 | 252
      6 | 2015-03-27 | 2015-11-30 | 248
      8 | 2015-03-18 | |
      7 | 2015-03-28 | |


      Obrigada por acompanhar o blog!

      Excluir
  2. Ajudou bastante, Obrigado.

    ResponderExcluir
  3. Parabéns, Belo trabalho

    ResponderExcluir
  4. Muito obrigado por compartilhar os seus conhecimentos!

    ResponderExcluir
  5. adorei as dicas, seus exemplos me ajudaram muito, obrigado!

    ResponderExcluir
  6. Cara se na tabela eu não tiver o data_final em alguns cadastros, como posso estar fazerndo?

    ResponderExcluir