Time difference in oracle - oracle

Hi i have the following table which contains Start time,end time, total time
STARTTIME | ENDTIME | TOTAL TIME TAKEN |
02-12-2013 01:24:00 | 02-12-2013 04:17:00 | 02:53:00 |
I need to update the TOTAL TIME TAKEN field as above using the update query in oracle
For that I have tried the following select query
select round((endtime-starttime) * 60 * 24,2),
endtime,
starttime
from purge_archive_status_log
but I'm getting 02.53 as a result, but my expectation format is 02:53:00 Please let me know how can I do this?

There is probably no reason to have that total_time_taken column in your table at all, you can always calculate it's value. But If you insist on keeping it, it would be better to recreated it as column of interval day to second data type, not varchar2(assuming that that's its current data type). So here are two queries for you to choose from, one returns value of interval day to second data type and another one value of varchar2 data type:
This query returns difference between two dates as a value of interval day to second data type:
SQL> with t1(starttime, endtime, total_time_taken ) as(
2 select to_date('02-12-2013 01:24:00', 'dd/mm/yyyy hh24:mi:ss')
3 , to_date('02-12-2013 04:17:00', 'dd/mm/yyyy hh24:mi:ss')
4 , '02:53:00'
5 from dual
6 )
7 select starttime
8 , endtime
9 , (endtime - starttime) day(0) to second(0) as total_time_taken
10 from t1
11 ;
Result:
STARTTIME ENDTIME TOTAL_TIME_TAKEN
----------- ----------- ----------------
02-12-2013 01:24:00 02-12-2013 04:17:00 +0 02:53:00
This query returns difference between two dates as a value of varchar2 data type:
SQL> with t1(starttime, endtime, total_time_taken ) as(
2 select to_date('02-12-2013 01:24:00', 'dd/mm/yyyy hh24:mi:ss')
3 , to_date('02-12-2013 04:17:00', 'dd/mm/yyyy hh24:mi:ss')
4 , '02:53:00'
5 from dual
6 )
7 select starttime
8 , endtime
9 , to_char(extract(hour from res), 'fm00') || ':' ||
10 to_char(extract(minute from res), 'fm00') || ':' ||
11 to_char(extract(second from res), 'fm00') as total_time_taken
12 from(select starttime
13 , endtime
14 , total_time_taken
15 , (endtime - starttime) day(0) to second(0) as res
16 from t1
17 )
18 ;
Result:
STARTTIME ENDTIME TOTAL_TIME_TAKEN
----------- ----------- ----------------
02-12-2013 01:24:00 02-12-2013 04:17:00 02:53:00

Try this too,
WITH TIME AS (
SELECT to_date('02-12-2013 01:24:00', 'dd-mm-yyyy hh24:mi:ss') starttime,
to_date('02-12-2013 04:17:00', 'dd-mm-yyyy hh24:mi:ss') endTime
FROM dual)
SELECT to_char(TRUNC ((endTime - startTime)* 86400 / (60 * 60)), 'fm09')||':'||
to_char(TRUNC (MOD ((endTime - startTime)* 86400, (60*60)) / 60), 'fm09')||':'||
to_char(MOD((endTime - startTime)* 86400, 60), 'fm09') time_diff
FROM TIME;

Related

How to get the date difference between start date and end date in oracle as hours and minutes

I have a scenario in which for example,my start_date ='12-SEP-2018 00:01:00' and End_date ='13-SEP-2018 14:55:00' . The difference between the 2 dates must be found out in Hours and minutes like'12:20'. This must be achieved in oracle database. I tried using the following logic :
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;
I was able to get the hour difference but unable to get minutes along with it.
CREATE TABLE table_name ( start_date DATE, end_date DATE );
INSERT INTO table_name VALUES ( TIMESTAMP '2009-07-07 19:30:00', TIMESTAMP '2009-07-07 22:00:00' );
Then you can subtract one from the other and cast it to a DAY TO SECOND interval and then just EXTRACT the component parts of the time:
SELECT EXTRACT( DAY FROM difference ) AS days,
EXTRACT( HOUR FROM difference ) AS hours,
EXTRACT( MINUTE FROM difference ) AS minutes,
EXTRACT( SECOND FROM difference ) AS seconds
FROM (
SELECT ( end_date - start_date ) DAY TO SECOND AS difference
FROM table_name
);
Outputs:
DAYS | HOURS | MINUTES | SECONDS
---: | ----: | ------: | ------:
0 | 2 | 30 | 0
or you can use arithmetic to calculate the values:
SELECT TRUNC( 24 * ( end_date - start_date ) ) AS hours,
TRUNC( MOD( 24 * 60 * ( end_date - start_date ), 60 ) ) AS minutes,
ROUND( MOD( 24 * 60 * 60 * ( end_date - start_date ), 60 ) ) AS seconds
FROM table_name;
which outputs:
HOURS | MINUTES | SECONDS
----: | ------: | ------:
2 | 30 | 0
db<>fiddle here
Since you want a string value, an alternative based on your query attempt is to add the difference between your two date values (which is a numeric value, the number of days between them, including fractional days) to an arbitrary fixed date; and then convert the result of that to a string:
SELECT to_char(date '0001-01-01'
+ (to_date('2009-07-07 22:00', 'YYYY-MM-DD hh24:mi') - to_date( '2009-07-07 19:30', 'YYYY-MM-DD hh24:mi')),
'HH24:MI') as diff
FROM dual;
DIFF
-----
02:30
If the difference can exceed 24 hours then you need to decide how to report that; if you want to include days as a separate figure then you can still use this approach, but need to subtract one (if your fixed date is the first) from the difference before formatting as a string:
SELECT to_char(date '0001-01-01'
+ (to_date('2009-07-08 22:00', 'YYYY-MM-DD hh24:mi') - to_date( '2009-07-07 19:30', 'YYYY-MM-DD hh24:mi'))
- 1,
'DDD:HH24:MI') as diff
FROM dual;
DIFF
---------
001:02:30
If you want the 'hours' value to be higher instead - e.g. '26:30' in this example - then it gets rather more complicated; I see #MTO has added the 'arithmetic' approach already so I won't repeat that. But then might be better off going down the extract() route (which you should consider anyway as it's more flexible and elegant...)

Convert time from a format to an int in Oracle

I can't seem to figure this out. I have some rows with time in the format 00:00:00 (hh:mm:ss) and i need to calculate the total time it takes for a task.
I am unable to sum this data. Can someone advise on a way to convert this to a format i can sum or a method to calculate the total time for the task.
Thanks for any assistance. This is in an Oracle DB.
Convert your time string to a date and subtract the equivalent date at midnight to give you an number as a fraction of a day. You can then sum this number and convert it to an interval:
Oracle Setup:
CREATE TABLE test_data( value ) AS
SELECT '01:23:45' FROM DUAL UNION ALL
SELECT '12:34:56' FROM DUAL UNION ALL
SELECT '23:45:00' FROM DUAL;
Query:
SELECT NUMTODSINTERVAL(
SUM( TO_DATE( value, 'HH24:MI:SS' ) - TO_DATE( '00:00:00', 'HH24:MI:SS' ) ),
'DAY'
) AS total_time_taken
FROM test_data;
Output:
| TOTAL_TIME_TAKEN |
| :---------------------------- |
| +000000001 13:43:41.000000000 |
db<>fiddle here
Update including durations longer than 23:59:59.
Oracle Setup:
CREATE TABLE test_data( value ) AS
SELECT '1:23:45' FROM DUAL UNION ALL
SELECT '12:34:56' FROM DUAL UNION ALL
SELECT '23:45:00' FROM DUAL UNION ALL
SELECT '48:00:00' FROM DUAL;
Query:
SELECT NUMTODSINTERVAL(
SUM(
DATE '1970-01-01'
+ NUMTODSINTERVAL( SUBSTR( value, 1, HM - 1 ), 'HOUR' )
+ NUMTODSINTERVAL( SUBSTR( value, HM + 1, MS - HM - 1 ), 'MINUTE' )
+ NUMTODSINTERVAL( SUBSTR( value, MS + 1 ), 'SECOND' )
- DATE '1970-01-01'
),
'DAY'
) AS total_time
FROM (
SELECT value,
INSTR( value, ':', 1, 1 ) AS HM,
INSTR( value, ':', 1, 2 ) AS MS
FROM test_data
);
Output:
| TOTAL_TIME |
| :---------------------------- |
| +000000003 13:43:41.000000000 |
db<>fiddle here
Even better would be if you changed your table to hold the durations as intervals rather than as strings then everything becomes much simpler:
Oracle Setup:
CREATE TABLE test_data( value ) AS
SELECT INTERVAL '1:23:45' HOUR TO SECOND FROM DUAL UNION ALL
SELECT INTERVAL '12:34:56' HOUR TO SECOND FROM DUAL UNION ALL
SELECT INTERVAL '23:45:00' HOUR TO SECOND FROM DUAL UNION ALL
SELECT INTERVAL '48:00:00' HOUR TO SECOND FROM DUAL;
Query:
SELECT NUMTODSINTERVAL(
SUM( DATE '1970-01-01' + value - DATE '1970-01-01' ),
'DAY'
) AS total_time
FROM test_data;
Output:
| TOTAL_TIME |
| :---------------------------- |
| +000000003 13:43:41.000000000 |
db<>fiddle here

Selecting every 3 seconds data rows between 2 dates

I have a requirement to take every 3 seconds data within the specific time interval in SQL. I am new to SQL so can anyone help me on the scenario
This is my select query which returns all the values but i need data for every 3 seconds only
SELECT ton_nbr
FROM
icr_file_interface
WHERE
(
reading_dttm BETWEEN
TO_DATE(concat('2016-10-19',to_char(0930)),'yyyy-mm-dd HH24MISS')
AND TO_DATE(concat('2016-10-19',to_char('0945')),'yyyy-mm-dd HH24MISS')
)
AND
(
ton_nbr BETWEEN
(SELECT value FROM text_para WHERE para_cd='ICR_ST_RNG')
AND (SELECT value FROM text_para WHERE para_cd='ICR_ED_RNG')
)
If you only need to subtract 3 seconds from a date, you can use the following:
SQL> select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),
2 to_char(sysdate - 3*1/24/60/60, 'yyyy-mm-dd hh24:mi:ss')
3 from dual;
TO_CHAR(SYSDATE,'YY TO_CHAR(SYSDATE-3*1
------------------- -------------------
2016-10-19 09:38:17 2016-10-19 09:38:14
Given that sysdate -1 means "subtract one day to sysdate", you can derive the number of seconds you need with a bit af arithmetic
This selects you data between last 3 seconds. Hope you got the idea.
select ton_nbr
from icr_file_interface
where reading_dttm between dateadd(ss, -3, getdate()) and getdate() ;

subtraction Minutes and Seconds from Data in PL\SQL

I have a table contains information about calls, each call has start date, and end date with the following format :
YYYY-MM-DD HH:MM:SS
how to take the difference between start date and end date in minutes or seconds ?
and how to delete seconds or minutes from Date ?, for example (2015-12-23 20:20:50) - 10 seconds = 2015-12-23 20:20:40
Is this what you're after??
drop table junk;
create table junk (
id number,
start_date date,
end_date date
)
/
insert into junk values ( 1, to_date('23-dec-2015 20:20:40', 'dd-mon-yyyy hh24:mi:ss'), to_date('23-dec-2015 20:20:50', 'dd-mon-yyyy hh24:mi:ss') );
insert into junk values ( 1, to_date('23-dec-2015 20:20:40', 'dd-mon-yyyy hh24:mi:ss'), to_date('23-dec-2015 20:21:50', 'dd-mon-yyyy hh24:mi:ss') );
insert into junk values ( 1, to_date('23-dec-2015 20:20:40', 'dd-mon-yyyy hh24:mi:ss'), to_date('23-dec-2015 22:21:50', 'dd-mon-yyyy hh24:mi:ss') );
commit;
select id, start_date, end_date,
end_date - start_date diff_days,
(end_date - start_date)*24 diff_hrs,
(end_date - start_date)*24*60 diff_min,
(end_date - start_date)*24*60*60 diff_sec,
trunc(end_date,'MI') no_seconds
from junk
/
ID START_DATE END_DATE DIFF_DAYS DIFF_HRS DIFF_MIN DIFF_SEC NO_SECONDS
---------- -------------------- -------------------- ---------- ---------- ---------- ---------- --------------------
1 23-dec-2015 20:20:40 23-dec-2015 20:20:50 .000115741 .002777778 .166666667 10 23-dec-2015 20:20:00
1 23-dec-2015 20:20:40 23-dec-2015 20:21:50 .000810185 .019444444 1.16666667 70 23-dec-2015 20:21:00
1 23-dec-2015 20:20:40 23-dec-2015 22:21:50 .084143519 2.01944444 121.166667 7270 23-dec-2015 22:21:00
SQL>
[edit]
just noticed I think you might have also been asking to delete a set # of seconds from a date value.
So if we want to delete 15 days, we could:
end_date - 15
to delete 15 hours:
end_date - (15/24)
... etc, until 15 seconds:
end_date - (15/24/60/60)
;)

How to find the time difference with respect to date in Oracle?

I want to find the time difference between the value in the column of type Date and the fixed time of that particular date.
Consider,
value in column - 4/16/2011 4:00:19 PM
Fixed time as - 3:00:00 PM
I am expecting the answer as 1hr 0min 19sec ago. Whatever the type I'm ok with it.
Thanks
Since you don't care what data type is returned, I'd probably cast to a timestamp so that you can get an interval day to second returned.
SQL> select cast( sysdate as timestamp ) from dual
2 ;
CAST(SYSDATEASTIMESTAMP)
---------------------------------------------------------------------------
15-MAR-15 04.05.46.000000 PM
SQL> ed
Wrote file afiedt.buf
1 select cast( sysdate as timestamp ) -
2 cast( trunc(sysdate) + interval '15' hour as timestamp )
3* from dual
4 /
CAST(SYSDATEASTIMESTAMP)-CAST(TRUNC(SYSDATE)+INTERVAL'15'HOURASTIMESTAMP)
---------------------------------------------------------------------------
+000000000 01:06:18.000000
If you want to return a string rather than an interval, you can use extract to extract data from the interval
SQL> ed
Wrote file afiedt.buf
1 select extract( hour from delta ) || ' hours, ' ||
2 extract( minute from delta ) || ' minutes, ' ||
3 extract( second from delta ) || ' seconds ago'
4 from (
5 select cast( sysdate as timestamp ) -
6 cast( trunc(sysdate) + interval '15' hour as timestamp ) delta
7 from dual
8* )
SQL> /
EXTRACT(HOURFROMDELTA)||'HOURS,'||EXTRACT(MINUTEFROMDELTA)||'MINUTES,'||EXTRACT(
--------------------------------------------------------------------------------
1 hours, 10 minutes, 46 seconds ago

Resources