Problema:
Você tem duas colunas do tipo
datetime
e você deseja calcular a diferença entre eles. 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 segundos):
SELECT id, partida, chegada, DATEDIFF(segundo, partida, chegada) AS diferença da 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 a
arrival
e a partida em T-SQL, use o DATEDIFF(datepart, startdate, enddate)
função. O datepart
argumento pode ser microsecond
, second
, minute
, hour
, day
, week
, month
, quarter
, ou year
. Aqui, você gostaria de obter a diferença em segundos, então escolha o segundo. Para obter a diferença em horas, escolha hour
; para a diferença em meses, escolha month
, etc. A startdate
e a enddate
os argumentos são o datetime
inicial e final colunas, respectivamente (aqui, departure
e arrival
, respectivamente). Solução 2 (diferença em dias, horas, minutos e segundos):
WITH Difference_in_seconds AS ( SELECT id, partida, chegada, DATEDIFF(SECOND, partida, chegada) AS segundos da viagem),diferenças AS (SELECT id, partida, chegada, segundos, segundos % 60 AS segundos_parte, segundos % 3600 AS minutos_parte, 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 a
arrival
e a departure
em segundos, usando o DATEDIFF()
função (o primeiro CTE, chamado difference_in_seconds
), assim como na Solução 1. Em seguida, 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 operador %. 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:seconds % 3600 AS minutes_part
Da mesma forma, existem
3600 * 24
segundos em um dia, para calcular quantos segundos existem em hours_part
, escrever: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 o FLOOR()
funcionar 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 umdatetime
diferença como texto. Você pode modificar facilmente a solução para obter apenas os números sem nenhum texto. Você também pode armazenar dias, horas, minutos e segundos em diferentes colunas:
FLOOR(seconds / 3600 / 24) AS dias,FLOOR(hours_part / 3600) AS horas,FLOOR(minutes_part / 60) AS minutos,seconds_part AS segundos