Problema:
Você tem duas colunas do tipo timestamp e deseja calcular a diferença entre elas.
Exemplo:
Na
travel
tabela, há três colunas:id
, departure
, e arrival
. Você gostaria de calcular a diferença entre a arrival
e a departure
. A
travel
tabela fica assim:id | partida | chegada |
---|---|---|
1 | 2018-03-25 12:00:00 | 2018-04-05 07:30:00 |
2 | 2019-09-12 15:50:00 | 23/10/2019 10:30:30 |
3 | 2018-07-14 16:15:00 | 2018-07-14 20:40:30 |
4 | 2018-01-05 08:35:00 | 2019-01-08 14:00:00 |
Solução 1 (diferença em dias, horas, minutos ou segundos):
SELECT id, partida, chegada, TIMESTAMPDIFF(SECOND, partida, chegada) AS diferençaFROM viagem;
O resultado é:
id | partida | chegada | diferença |
---|---|---|---|
1 | 2018-03-25 12:00:00 | 2018-04-05 07:30:00 | 934200 |
2 | 2019-09-12 15:50:00 | 23/10/2019 10:30:30 | 3523230 |
3 | 2018-07-14 16:15:00 | 2018-07-14 20:40:30 | 15930 |
4 | 2018-01-05 08:35:00 | 2019-01-08 14:00:00 | 31814700 |
Discussão:
Para calcular a diferença entre os timestamps no MySQL, use o
TIMESTAMPDIFF(unit, start, end)
função. O argumento da unidade pode ser MICROSECOND
, SECOND
, MINUTE
, HOUR
, DAY
, WEEK
, MONTH
, QUARTER
, ou YEAR
. Para obter a diferença em segundos como fizemos aqui, escolha SECOND
. Para obter a diferença em minutos, escolha MINUTE
; para a diferença em horas, escolha HOUR
, etc. Os argumentos end e start são o timestamp final e o timestamp inicial, respectivamente (aqui, departure
e arrival
, respectively
). Solução 2 (diferença em dias, horas, minutos e segundos):
WITH Difference_in_seconds AS ( SELECT id, partida, chegada, TIMESTAMPDIFF(SECOND, partida, chegada) AS segundos da viagem),diferenças AS (SELECT id, partida, chegada, segundos, MOD(segundos, 60) AS segundos_parte, MOD (segundos, 3600) AS minutos_parte, MOD(segundos, 3600 * 24) AS horas_parte FROM diferença_em_segundos)SELECT id, partida, chegada, CONCAT( FLOOR(segundos / 3600 / 24), 'dias', FLOOR(horas_parte / 3600), ' horas ', FLOOR(minutos_parte / 60), 'minutos', segundos_parte, 'segundos' ) AS diferençaFROM diferenças;
O resultado é:
id | partida | chegada | diferença |
---|---|---|---|
1 | 2018-03-25 12:00:00 | 2018-04-05 07:30:00 | 10 dias 19 horas 30 minutos 0 segundos |
2 | 2019-09-12 15:50:00 | 23/10/2019 10:30:30 | 40 dias 18 horas 40 minutos e 30 segundos |
3 | 2018-07-14 16:15:00 | 2018-07-14 20:40:30 | 0 dias 4 horas 25 minutos 30 segundos |
4 | 2018-01-05 08:35:00 | 2019-01-08 14:00:00 | 368 dias 5 horas 25 minutos 0 segundos |
Discussão:
Primeiro, calcule a diferença entre os timestamps em segundos, usando o
TIMESTAMPDIFF()
função (o primeiro CTE, chamado difference_in_seconds
), assim como na Solução 1. Calcule quantos segundos existem além dos minutos inteiros (seconds_part
) para ser usado posteriormente para calcular os segundos, quantos segundos existem em excesso de horas inteiras (minutes_part
) para ser usado posteriormente para calcular os minutos e quantos segundos existem além das horas inteiras (hours_part
) para ser usado posteriormente para calcular as horas. Para fazer isso, use o
MOD()
função. Por exemplo, uma hora tem 3600 segundos, então para descobrir quantos segundos existem em minutes_part
, encontre o resto da divisão por 3600 assim:MOD(seconds, 3600) AS minutes_part
Da mesma forma, existem
3600 * 24
segundos em um dia, para calcular quantos segundos existem em hours_part
, escrever:MOD(seconds, 3600 * 24) AS hours_part
Uma vez que esses restos são calculados (no segundo CTE, chamado
differences
), você pode finalmente obter a diferença em dias, horas, minutos e segundos. Para obter o número de segundos, minutos, horas e dias, divida o número de segundos no restante pelo número correspondente de segundos em dias, horas ou minutos. Por exemplo, para descobrir quantos minutos devem ser exibidos, use minutes_part
e divida-o por 60, pois há 60 minutos em uma hora. Você só precisa da parte inteira disso (ou seja, sem a parte decimal), então use a função FLOOR() assim:FLOOR(minutes_part / 60)
Finalmente, você só precisa exibir em uma string o que você calculou. Para fazer isso, use o
CONCAT()
função na consulta externa:CONCAT( FLOOR(seconds / 3600 / 24), ' days ', FLOOR(hours_part / 3600), ' hours ', FLOOR(minutes_part / 60), ' minutes ', seconds_part, 'seconds' ) AS diferença
A solução apresentada aqui retorna a última coluna como texto. Você pode modificar facilmente esta solução para exibi-la em algum outro formato. Você também pode exibir os números em colunas separadas, assim:
FLOOR(seconds / 3600 / 24) AS dias,FLOOR(hours_part / 3600) AS horas,FLOOR(minutes_part / 60) AS minutos,seconds_part AS segundos