Calcular la diferencia entre 2 fechas / horas en Oracle SQL


88

Tengo una mesa de la siguiente manera:

Filename - varchar
Creation Date - Date format dd/mm/yyyy hh24:mi:ss
Oldest cdr date - Date format dd/mm/yyyy hh24:mi:ss

¿Cómo puedo calcular la diferencia en horas, minutos y segundos (y posiblemente días) entre las dos fechas en Oracle SQL?

Gracias


Respuestas:


118

Puede restar fechas en Oracle. Esto le dará la diferencia en días. Multiplique por 24 para obtener horas, y así sucesivamente.

SQL> select oldest - creation from my_table;

Si su fecha se almacena como datos de caracteres, primero debe convertirla a un tipo de fecha.

SQL> select 24 * (to_date('2009-07-07 22:00', 'YYYY-MM-DD hh24:mi') 
             - to_date('2009-07-07 19:30', 'YYYY-MM-DD hh24:mi')) diff_hours 
       from dual;

DIFF_HOURS
----------
       2.5

Nota :

Esta respuesta se aplica a las fechas representadas por el tipo de datos de Oracle DATE. Oracle también tiene un tipo de datos TIMESTAMP, que también puede representar una fecha (con hora). Si resta TIMESTAMPvalores, obtiene un INTERVAL; para extraer valores numéricos, use la EXTRACTfunción.


3
¿Ha habido algún cambio en el comportamiento de Oracle en algún momento? Cuando resto una fecha de otra, obtengo un INTERVALtipo de datos, no un simple flotante.

2
@JonofAllTrades: No, cuando resta valores de tipo DATE, obtiene el número de días (como a NUMBER). Sin embargo, si resta TIMESTAMPvalores, obtiene INTERVALDS. Probablemente estás trabajando con valores TIMESTAMPy no con ellos DATE. Edité la respuesta.
sleske

Con respecto a su nota: los tipos de datos DATEy TIMESTAMPtienen un componente de tiempo (horas, minutos y segundos). TIMESTAMPtambién tiene un componente de tiempo de fracción de segundo (y potencialmente componentes de zona horaria).
MT0

"Esto le dará la diferencia en días". ¿Puede vincular a la documentación de Oracle, por favor?
Roland


16
declare
strTime1 varchar2(50) := '02/08/2013 01:09:42 PM';
strTime2 varchar2(50) := '02/08/2013 11:09:00 PM';
v_date1 date := to_date(strTime1,'DD/MM/YYYY HH:MI:SS PM');
v_date2 date := to_date(strTime2,'DD/MM/YYYY HH:MI:SS PM');
difrence_In_Hours number;
difrence_In_minutes number;
difrence_In_seconds number;
begin
    difrence_In_Hours   := (v_date2 - v_date1) * 24;
    difrence_In_minutes := difrence_In_Hours * 60;
    difrence_In_seconds := difrence_In_minutes * 60;

    dbms_output.put_line(strTime1);        
    dbms_output.put_line(strTime2);
    dbms_output.put_line('*******');
    dbms_output.put_line('difrence_In_Hours  : ' || difrence_In_Hours);
    dbms_output.put_line('difrence_In_minutes: ' || difrence_In_minutes);
    dbms_output.put_line('difrence_In_seconds: ' || difrence_In_seconds);        
end ;

Espero que esto ayude.


14
select 
    extract( day from diff ) Days, 
    extract( hour from diff ) Hours, 
    extract( minute from diff ) Minutes 
from (
        select (CAST(creationdate as timestamp) - CAST(oldcreationdate as timestamp)) diff   
        from [TableName] 
     );

Esto le dará tres columnas como Días, Horas y Minutos.


8

También puede probar esto:

select to_char(to_date('1970-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')+(end_date - start_date),'hh24:mi:ss')
       as run_time from some_table;

Muestra la hora en una forma más legible por humanos, como: 00:01:34. Si necesita también días, simplemente puede agregar DD a la última cadena de formato.


7

Puede utilizar la función to_timestamp para convertir las fechas en marcas de tiempo y realizar una operación de resta.

Algo como:

SELECT 
TO_TIMESTAMP ('13.10.1990 00:00:00','DD.MM.YYYY HH24:MI:SS')  - 
TO_TIMESTAMP ('01.01.1990:00:10:00','DD.MM.YYYY:HH24:MI:SS')
FROM DUAL

Probé tanto to_date como to_timestamp y ambos me dan una respuesta en días, redondeada hacia abajo, de modo que si la diferencia es de 1 hora recibo una respuesta de 0, multiplicando esto por 24 da 0. Recibo la respuesta correcta si escribo la fecha y hora, pero no puedo hacer esto para 25 m filas. ¿Alguna idea?
Steve

3
Si utiliza una resta entre marcas de tiempo, obtendrá otra marca de tiempo en un formato como "DÍAS HORA: MIN: SECS.milisecs". Puede truncar esto para obtener el valor que necesita
HyLian

6
La resta entre marcas de tiempo devuelve un tipo de datos INTERVAL. Puede usar la función EXTRACT para devolver varias partes de un intervalo, por ejemplo, seleccione extraer (hora de (marca de tiempo '2009-12-31 14:00:00' - marca de tiempo '2009-12-31 12:15:00')) hr de dual; Nota: Eso solo muestra la parte de la HORA, por lo que si la diferencia es 1 día y 1 hora, mostrará 1, no 25.
Gary Myers

5

Calcule la edad desde HIREDATE hasta la fecha del sistema de su computadora

SELECT HIREDATE||'        '||SYSDATE||'       ' ||
TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12) ||' YEARS '||
TRUNC((MONTHS_BETWEEN(SYSDATE,HIREDATE))-(TRUNC(MONTHS_BETWEEN(SYSDATE,HIREDATE)/12)*12))||
'MONTHS' AS "AGE  "  FROM EMP;

3
select days||' '|| time from (
SELECT to_number( to_char(to_date('1','J') +
    (CLOSED_DATE - CREATED_DATE), 'J') - 1)  days,
   to_char(to_date('00:00:00','HH24:MI:SS') +
      (CLOSED_DATE - CREATED_DATE), 'HH24:MI:SS') time
 FROM  request  where REQUEST_ID=158761088 );

3

En Oracle 11g

SELECT end_date - start_date AS day_diff FROM tablexxx
suppose the starT_date end_date is define in the tablexxx

2

Si selecciona dos fechas de ' su_tabla ' y también desea ver el resultado como una salida de una sola columna (por ejemplo, ' días - hh: mm: ss '), podría usar algo como esto. Primero puede calcular el intervalo entre estas dos fechas y luego exportar todos los datos que necesita de ese intervalo:

         select     extract (day from numtodsinterval (second_date
                                                   - add_months (created_date,
                                                                 floor (months_between (second_date,created_date))),
                                                   'day'))
             || ' days - '
             || extract (hour from numtodsinterval (second_date
                                                    - add_months (created_date,
                                                                  floor (months_between (second_date,created_date))),
                                                    'day'))
             || ':'
             || extract (minute from numtodsinterval (second_date
                                                      - add_months (created_date,
                                                                    floor (months_between (second_date, created_date))),
                                                      'day'))
             || ':'
             || extract (second from numtodsinterval (second_date
                                                      - add_months (created_date,
                                                                    floor (months_between (second_date, created_date))),
                                                      'day'))
     from    your_table

Y eso debería darte un resultado como este: 0 días - 1:14:55


1
select (floor(((DATE2-DATE1)*24*60*60)/3600)|| ' : ' ||floor((((DATE2-DATE1)*24*60*60) -floor(((DATE2-DATE1)*24*60*60)/3600)*3600)/60)|| '  ' ) as time_difference from TABLE1 

1

Si desea algo que parezca un poco más simple, intente esto para buscar eventos en una tabla que ocurrieron en el último minuto:

Con esta entrada puede jugar con los valores decimales hasta que obtenga el valor de minutos que desee. El valor .0007 pasa a ser de 1 minuto en lo que respecta a los dígitos significativos de la fecha del sistema. Puede usar múltiplos de eso para obtener cualquier otro valor que desee:

select (sysdate - (sysdate - .0007)) * 1440 from dual;

El resultado es 1 (minuto)

Entonces es una cuestión sencilla de comprobar

select * from my_table where (sysdate - transdate) < .00071;

1
(TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*60*60*24 sum_seconds,
         (TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*60*24 sum_minutes,
         (TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi'))*24 sum_hours,
         (TO_DATE(:P_comapre_date_1, 'dd-mm-yyyy hh24:mi') - TO_DATE(:P_comapre_date_2, 'dd-mm-yyyy hh24:mi')) sum_days 

1
select to_char(actual_start_date,'DD-MON-YYYY hh24:mi:ss') start_time,
to_char(actual_completion_date,'DD-MON-YYYY hh24:mi:ss') end_time,
floor((actual_completion_date-actual_start_date)*24*60)||'.'||round(mod((actual_completion_date-actual_start_date)*24*60*60,60)) diff_time
from fnd_concurrent_requests 
order by request_id desc;  

0
$sql="select bsp_bp,user_name,status,
to_char(ins_date,'dd/mm/yyyy hh12:mi:ss AM'),
to_char(pickup_date,'dd/mm/yyyy hh12:mi:ss AM'),
trunc((pickup_date-ins_date)*24*60*60,2),message,status_message 
from valid_bsp_req where id >= '$id'"; 

0

Esto contará el tiempo entre las fechas hasta:

SELECT
  (TO_CHAR( TRUNC (ROUND(((sysdate+1) - sysdate)*24,2))*60,'999999')
  +
  TO_CHAR(((((sysdate+1)-sysdate)*24)- TRUNC(ROUND(((sysdate+1) - sysdate)*24,2)))/100*60 *100, '09'))/60
FROM dual

0

Aquí tienes otra opción:

with tbl_demo AS
    (SELECT TO_DATE('11/26/2013 13:18:50', 'MM/DD/YYYY HH24:MI:SS') dt1
   , TO_DATE('11/28/2013 21:59:12', 'MM/DD/YYYY HH24:MI:SS') dt2 
     FROM dual)
SELECT dt1
     , dt2
     , round(dt2 - dt1,2) diff_days
     , round(dt2 - dt1,2)*24 diff_hrs
     , numtodsinterval((dt2 - dt1),'day') diff_dd_hh_mm_ss
  from tbl_demo;

0

Consulta única que devolverá la diferencia horaria de dos columnas de marca de tiempo:

select INS_TS, MAIL_SENT_TS, extract( hour from (INS_TS - MAIL_SENT_TS) ) timeDiff 
from MAIL_NOTIFICATIONS;

0

Si desea obtener la fecha, difiera el uso de la tabla y la columna.

SELECT TO_DATE( TO_CHAR(COLUMN_NAME_1, 'YYYY-MM-DD'), 'YYYY-MM-DD') - 
       TO_DATE(TO_CHAR(COLUMN_NAME_2, 'YYYY-MM-DD') , 'YYYY-MM-DD')  AS DATEDIFF       
FROM TABLE_NAME;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.