sql >> Base de Datos >  >> RDS >> Database

Cómo calcular la diferencia entre dos fechas y horas en T-SQL

Problema:

Tienes dos columnas del tipo datetime y quieres calcular la diferencia entre ellos.

Ejemplo:

En el travel tabla, hay tres columnas:id , departure y arrival . Le gustaría calcular la diferencia entre la arrival y la departure .

El travel la tabla se ve así:

id salida llegada
1 2018-03-25 12:00:00 2018-04-05 07:30:00
2 2019-09-12 15:50:00 2019-10-23 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

Solución 1 (diferencia en segundos):

SELECT
  id,
  departure,
  arrival,
  DATEDIFF(second, departure, arrival) AS difference
FROM travel;

El resultado es:

id salida llegada diferencia
1 2018-03-25 12:00:00 2018-04-05 07:30:00 934200
2 2019-09-12 15:50:00 2019-10-23 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

Discusión:

Para calcular la diferencia entre la arrival y la salida en T-SQL, use DATEDIFF(datepart, startdate, enddate) función. El datepart el argumento puede ser microsecond , second , minute , hour , day , week , month , quarter , o year . Aquí, le gustaría obtener la diferencia en segundos, así que elija el segundo. Para obtener la diferencia en horas, elija hour; para la diferencia en meses, elija month , etc. La startdate y la enddate los argumentos son el inicio y el final datetime columnas, respectivamente (aquí, departure y arrival , respectivamente).

Solución 2 (diferencia en días, horas, minutos y segundos):

WITH difference_in_seconds AS (
  SELECT
    id,
    departure,
    arrival,
    DATEDIFF(SECOND, departure, arrival) AS seconds
  FROM travel
),

differences AS (
  SELECT
    id,
    departure,
    arrival,
    seconds,
    seconds % 60 AS seconds_part,
    seconds % 3600 AS minutes_part,
    seconds % (3600 * 24) AS hours_part
  FROM difference_in_seconds
)

SELECT
  id,
  departure,
  arrival,
  CONCAT(
    FLOOR(seconds / 3600 / 24), ' days ',
    FLOOR(hours_part / 3600), ' hours ',
    FLOOR(minutes_part / 60), ' minutes ',
    seconds_part, ' seconds'
  ) AS difference
FROM differences;

El resultado es:

id salida llegada diferencia
1 2018-03-25 12:00:00 2018-04-05 07:30:00 10 días 19 horas 30 minutos 0 segundos
2 2019-09-12 15:50:00 2019-10-23 10:30:30 40 días 18 horas 40 minutos 30 segundos
3 2018-07-14 16:15:00 2018-07-14 20:40:30 0 días 4 horas 25 minutos 30 segundos
4 2018-01-05 08:35:00 2019-01-08 14:00:00 368 días 5 horas 25 minutos 0 segundos

Discusión:

Primero, calcula la diferencia entre la arrival y la departure en segundos, usando DATEDIFF() función (el primer CTE, denominado difference_in_seconds ), tal como en la Solución 1. Luego, calcule cuántos segundos hay en exceso de los minutos completos (seconds_part ) para ser utilizado posteriormente para calcular los segundos, cuántos segundos hay en exceso de horas enteras (minutes_part ) para ser utilizado más tarde para calcular los minutos y cuántos segundos hay en exceso de las horas enteras (hours_part ) para ser utilizado más tarde para calcular las horas.

Para hacer esto, use el operador %. Por ejemplo, una hora tiene 3600 segundos, así que para saber cuántos segundos hay en minutes_part , encuentre el resto de la división por 3600 así:

seconds % 3600 AS minutes_part

Del mismo modo, hay 3600 * 24 segundos en un día, para calcular cuántos segundos hay en hours_part , escribe:

seconds % (3600 * 24) AS hours_part

Una vez calculados estos residuos (en el segundo CTE, denominado differences ), finalmente puede obtener la diferencia en días, horas, minutos y segundos. Para obtener la cantidad de segundos, minutos, horas y días, divida la cantidad de segundos en el resto por la cantidad correspondiente de segundos en días, horas o minutos. Por ejemplo, para averiguar cuántos minutos se deben mostrar, tome minutes_part y divídalo por 60, ya que hay 60 minutos en una hora. Solo necesita la parte entera de esto (es decir, sin la parte decimal), así que use FLOOR() funcionar así:

FLOOR(minutes_part / 60)

Finalmente, simplemente necesita mostrar en una cadena lo que ha calculado. Para hacer esto, use CONCAT() función en la consulta externa:

CONCAT(
    FLOOR(seconds / 3600 / 24), ' days ',
    FLOOR(hours_part / 3600), ' hours ',
    FLOOR(minutes_part / 60), ' minutes ',
    seconds_part, ' seconds'
  ) AS difference

La solución presentada aquí devuelve un datetime diferencia como texto. Puede modificar fácilmente la solución para obtener solo los números sin ningún texto. También puede almacenar días, horas, minutos y segundos en diferentes columnas:

FLOOR(seconds / 3600 / 24) AS days,
FLOOR(hours_part / 3600) AS hours,
FLOOR(minutes_part / 60) AS minutes,
seconds_part AS seconds