Calcola la differenza tra 2 date / orari in Oracle SQL


88

Ho una tabella come segue:

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

Come posso calcolare la differenza in ore minuti e secondi (e possibilmente giorni) tra le due date in Oracle SQL?

Grazie


Risposte:


118

Puoi sottrarre le date in Oracle. Questo ti darà la differenza in giorni. Moltiplica per 24 per ottenere le ore e così via.

SQL> select oldest - creation from my_table;

Se la tua data è memorizzata come dati carattere, devi prima convertirla in un tipo di data.

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 :

Questa risposta si applica alle date rappresentate dal tipo di dati Oracle DATE. Oracle ha anche un tipo di dati TIMESTAMP, che può anche rappresentare una data (con l'ora). Se sottrai TIMESTAMPvalori, ottieni un INTERVAL; per estrarre valori numerici, utilizzare la EXTRACTfunzione.


3
C'è stato un cambiamento nel comportamento di Oracle ad un certo punto? Quando sottraggo una data da un'altra ottengo un INTERVALtipo di dati, non un semplice float.

2
@JonofAllTrades: No, quando sottrai valori di tipo DATE, ottieni il numero di giorni (come a NUMBER). Tuttavia, se sottrai TIMESTAMPvalori, ottieni INTERVALDS. Probabilmente stai lavorando con TIMESTAMPe non con DATEvalori. Ho modificato la risposta.
sleske il

Per quanto riguarda la tua nota - Entrambi i tipi di dati DATEe TIMESTAMPhanno un componente tempo (ore, minuti e secondi). TIMESTAMPha anche una componente temporale frazionaria dei secondi (e potenzialmente componenti del fuso orario).
MT0

"Questo ti darà la differenza in giorni." Puoi collegarti alla documentazione Oracle per favore?
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 ;

Spero che sia di aiuto.


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] 
     );

Questo ti darà tre colonne come giorni, ore e minuti.


8

Puoi anche provare questo:

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;

Visualizza l'ora in una forma più leggibile dall'uomo, come: 00:01:34. Se hai bisogno anche di giorni puoi semplicemente aggiungere DD all'ultima stringa di formattazione.


7

È possibile utilizzare la funzione to_timestamp per convertire le date in timestamp ed eseguire un'operazione di sottrazione.

Qualcosa di simile a:

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

Ho provato sia to_date che to_timestamp ed entrambi mi danno una risposta in giorni, arrotondata per difetto, quindi se la differenza è 1 ora ricevo una risposta di 0, moltiplicandola per 24 dà 0. Ricevo la risposta corretta se digito la data e l'ora ma non posso farlo per 25 milioni di righe. qualche idea?
Steve

3
Utilizzando una sottrazione tra i timestamp, verrebbe restituito un altro timestamp in un formato come "DAYS HOUR: MINS: SECS.milisecs". Potresti troncarlo per ottenere il valore di cui hai bisogno
HyLian

6
La sottrazione tra timestamp restituisce un tipo di dati INTERVAL. È possibile utilizzare la funzione ESTRATTA per restituire varie parti di un intervallo, ad esempio selezionare l'estrazione (ora da (timestamp '2009-12-31 14:00:00' - timestamp '2009-12-31 12:15:00')) hr da dual; Nota: questo mostra solo la parte dell'ORA, quindi se la differenza è di 1 giorno e 1 ora, questo mostrerà 1 non 25.
Gary Myers

5

Calcola l'età da HIREDATE alla data di sistema del tuo computer

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

In oracolo 11g

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

2

Se selezioni due date da " tua_tabella " e vuoi anche vedere il risultato come output di una singola colonna (es. " Giorni - hh: mm: ss ") potresti usare qualcosa di simile. Per prima cosa puoi calcolare l'intervallo tra queste due date e successivamente esportare tutti i dati necessari da quell'intervallo:

         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

E questo dovrebbe darti un risultato come questo: 0 giorni - 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

Se vuoi qualcosa che sembri un po 'più semplice, prova questo per trovare eventi in una tabella che si sono verificati nell'ultimo minuto:

Con questa voce puoi armeggiare con i valori decimali fino a ottenere il valore minuto che desideri. Il valore .0007 sembra essere 1 minuto per quanto riguarda le cifre significative di sysdate. Puoi utilizzare multipli di quello per ottenere qualsiasi altro valore che desideri:

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

Il risultato è 1 (minuto)

Quindi è una questione semplice da verificare

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

Questo conterà il tempo tra le date:

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

Ecco un'altra opzione:

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

Singola query che restituirà la differenza di orario di due colonne di timestamp:

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

0

Se si desidera ottenere il differimento della data dall'utilizzo di tabella e colonna.

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.