subtraction Minutes and Seconds from Data in PL\SQL - oracle

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

Related

How to calculate the difference of HH:MM:SS between two dates in oracle sql?

I have a table abc as:
-- start_time |end_time | total_time_taken
-- 27.05.2020 00:52:48 |27.05.2020 02:08:33 |
I want to set the value of total_time_taken as the difference of end_time-start_time. in the format "HH:MM:SS".I searched the similar topic but didnot find the exact answer.
My expected output is like : 01:44:12 (HH:MM:SS)
So,i tried :
SELECT To_Char(end_time,'HH24:MM:SS'),To_Char(start_time,'HH24:MM:SS'),
To_Char(end_time,'HH24:MM:SS')-To_Char(start_time,'HH24:MM:SS') FROM abc;
The datatypes of start_time,end_time,total_time_taken is DATE.Please help me to find the solution.
If you cast those dates as timestamps, you can easily subtract them and see relatively nice result:
SQL> with test (st, et) as
2 (select to_date('27.05.2020 00:52:48', 'dd.mm.yyyy hh24:mi:ss'),
3 to_date('27.05.2020 02:08:33', 'dd.mm.yyyy hh24:mi:ss')
4 from dual
5 )
6 select cast(et as timestamp) - cast(st as timestamp) diff
7 from test;
DIFF
--------------------------------------------------------------------------
+000000000 01:15:45.000000
SQL>
If you want to format it as you wanted (note that mm format mask is for months; mi is for minutes), then you could do some extracting - again from timestamp (won't work for date):
SQL> with test (st, et) as
2 (select to_date('27.05.2020 00:52:48', 'dd.mm.yyyy hh24:mi:ss'),
3 to_date('27.05.2020 02:08:33', 'dd.mm.yyyy hh24:mi:ss')
4 from dual
5 ),
6 diff as
7 (select cast(et as timestamp) - cast(st as timestamp) diff
8 from test
9 )
10 select extract(hour from diff) ||':'||
11 extract(minute from diff) ||':'||
12 extract(second from diff) diff
13 from diff;
DIFF
-------------------------------------------------------------------------
1:15:45
SQL>
You can further make it pretty (e.g. two digits for hours, using LPAD function). Or, you can even write your own function which will actually work on difference of DATE datatype values, do some calculations (using trunc function, subtractions, whatnot), but the above looks pretty elegant if compared to a home-made function.
The answer by Littlefoot is perfectly fine. This answer is just to show there is more than one way to get the result.
First, we can subtract one date from another and get the difference in days, then convert that difference to an interval.
with test (st, et) as
(select to_date('27.05.2020 00:52:48', 'dd.mm.yyyy hh24:mi:ss'),
to_date('27.05.2020 02:08:33', 'dd.mm.yyyy hh24:mi:ss')
from dual
)
select numtodsinterval(et-st, 'day') diff
from test;
Then, since we can't control interval formatting directly, we can add DIFF to an arbitrary date and then use built-in date formatting.
with test (st, et) as
(select to_date('27.05.2020 00:52:48', 'dd.mm.yyyy hh24:mi:ss'),
to_date('27.05.2020 02:08:33', 'dd.mm.yyyy hh24:mi:ss')
from dual
)
select to_char(date '1-1-1' + numtodsinterval(et-st, 'day'), 'hh24:mi:ss') diff
from test;
DIFF
--------
01:15:45

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...)

Decoding and Converting VARCHAR Time in Oracle

I need to query particular column in DB w/c is described as VARCHAR that I need to convert into Time Format (HH:MM) and then decode to its range value, to explain further... The column stores data when (time) a particular deal was made w/in the day and instead of returning the exact time it should return the time range it was done.
Col_1 is VARCHAR2(6)
select col_2, col_1 from table
Col_2 || Col_1
A || 9:56
B || 10:03
C || 21:53
My desired Output would be
Col_2 || Col_1
A || (09:00 - 10:00)
B || (10:00 - 11:00)
C || (2100 - 2200)
Really appreciate all your comments, as I'm stuck playing with this part for a couple of days now and its giving me nightmares, sorry I'm new to DB Oracle SQL stuff and still learning. :)
Like this?
In your output, 2100 - 2200 is not consistent with the rest; I ignored it.
What should happen when the input is like 10:00 even? That is in both 9:00-10:00 and in 10:00-11:00; I assumed you want the latter.
Finally, is 00:00 ok, or do you want that to be 24:00 instead (if it is at the end) - see the second example in my output.
with input_strings ( str ) as (
select '9:49' from dual union all
select '23:00' from dual
),
prep ( dt ) as (
select trunc(to_date(str, 'hh24:mi'),'hh') from input_strings
)
select to_char(dt, 'hh24:mi') || ' - ' || to_char(dt + 1/24, 'hh24:mi') as range
from prep;
RANGE
-------------
09:00 - 10:00
23:00 - 00:00
If you do to_date(col_1, 'HH24:MI') you'll get that tie on the first day of the month, as that what Oracle defaults to with no date specified. You can then truncate that to the hour, zeroing the minutes:
with t (col_2, col_1) as (
select 'A', '9:56' from dual
union all select 'B', '10:03' from dual
union all select 'C', '21:53' from dual
)
select col_2,
to_char(to_date(col_1, 'HH24:MI'), 'YYYY-MM-DD HH24:MI') as full_date,
to_char(trunc(to_date(col_1, 'HH24:MI'), 'HH24'), 'YYYY-MM-DD HH24:MI') as truncated
from t;
C FULL_DATE TRUNCATED
- ---------------- ----------------
A 2016-09-01 09:56 2016-09-01 09:00
B 2016-09-01 10:03 2016-09-01 10:00
C 2016-09-01 21:53 2016-09-01 21:00
That gives you the lower bound of your range. You can add an hour to the calculated date to get the upper limit, and then convert both back to string, and concatenate them together:
with t (col_2, col_1) as (
select 'A', '9:56' from dual
union all select 'B', '10:03' from dual
union all select 'C', '21:53' from dual
)
select col_2,
to_char(trunc(to_date(col_1, 'HH24:MI'), 'HH24'), 'HH24:MI') ||' - '||
to_char(trunc(to_date(col_1, 'HH24:MI') + 1/24, 'HH24'), 'HH24:MI')
from t;
C TO_CHAR(TRUNC
- -------------
A 09:00 - 10:00
B 10:00 - 11:00
C 21:00 - 22:00
You could also try to extract the hour value from your string and manipulate that, but then you have to manually deal with times between 23:00 and 00:00.
A third option is to use an interval instead of a date:
to_char(extract(hour from to_dsinterval('0 ' || col_1 || ':00')), 'FM00') ||':00 - '||
to_char(extract(hour from to_dsinterval('0 ' || col_1 || ':00')) + 1, 'FM00') ||':00'
but again this would show a time of say 23:15 as 23:00 - 24:00, so you'd need extra handling to show the upper bound as 00:00 in that case.

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

Time difference in 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;

Resources