Time in oracle with crossing over 0:00 - oracle

can you help me please.
I'm use:
round((24 * 60 * (to_date(EndPick, 'HH24:MI') - to_date(StartPick, 'HH24:MI'))), 2) as WorkTime
All time EndPick bigger then StartPick. But we have a chance, what Start bigger where
estimate time interval if there is a crossing over 00:00 into the next date?
In relult for example:
3
(minutes)

But we have a chance, what Start bigger where estimate time interval if there is a crossing over 00:00 into the next date?
Use a CASE expression and add a day if startpick > endpick:
SELECT round(
(24 * 60 * (to_date(EndPick, 'HH24:MI')
+ CASE
WHEN startpick > endpick
THEN INTERVAL '1' DAY
ELSE INTERVAL '0' DAY
END
- to_date(StartPick, 'HH24:MI')
)),
2
) as WorkTime
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name (startpick, endpick) AS
SELECT '00:00', '01:00' FROM DUAL UNION ALL
SELECT '23:00', '00:00' FROM DUAL;
Outputs:
WORKTIME
60
60
fiddle

Related

Oracle: splitting time range into days and calculation of duration

I'm developing code calculation service availability based on events, so I need to split events into daily "sub-events" and calculate duration of then.
So as input I have set of events like (EVENT_ID, START_TIME, END_TIME):
'event1';2021-05-01 12:30;2021-05-01 13:00
'event2';2021-05-03 10:55;2021-05-05 12:01
As output I'd like to get (EVENT_ID, DAY, DURATION_MINUTES):
'event1'; 2021-05-01; 30
'event2'; 2021-05-03; 785
'event2'; 2021-05-04; 1440
'event2'; 2021-05-05; 721
I can get it using procedures and cursor but this is not effective (the events database is quite big), so is there a way to do it using oracle sql query ? Any idea?
You appear to want a recursive query:
WITH days ( event_id, day, start_time, end_time ) AS (
SELECT event_id,
TRUNC( start_time ),
start_time,
end_time
FROM table_name
UNION ALL
SELECT event_id,
day + INTERVAL '1' DAY,
start_time,
end_time
FROM days
WHERE day + INTERVAL '1' DAY < end_time
)
SELECT event_id,
day,
ROUND(
(
LEAST(end_time, day + INTERVAL '1' DAY)
- GREATEST(start_time, day)
) * 24 * 60
) AS duration_minutes
FROM days
Which, for the sample data:
CREATE TABLE table_name ( event_id, start_time, end_time ) AS
SELECT 'event1', DATE '2021-05-01' + INTERVAL '12:30' HOUR TO MINUTE, DATE '2021-05-01' + INTERVAL '13:00' HOUR TO MINUTE FROM DUAL UNION ALL
SELECT 'event2', DATE '2021-05-03' + INTERVAL '10:55' HOUR TO MINUTE, DATE '2021-05-05' + INTERVAL '12:01' HOUR TO MINUTE FROM DUAL;
Outputs:
EVENT_ID
DAY
DURATION_MINUTES
event1
2021-05-01
30
event2
2021-05-03
785
event2
2021-05-04
1440
event2
2021-05-05
721
db<>fiddle here
If your Oracle version is 12 or higher, you can use a lateral join (in any of several equivalent formulations/syntaxes) to make the query faster. For example (using the table set up in MT0's answer):
select event_id, day, round(1440 * duration_days) as duration_minutes
from table_name cross join lateral
( select trunc(start_time) + level - 1 as day,
case when level = 1 and connect_by_isleaf = 1
then end_time - start_time
when level = 1 then 1 - (start_time - trunc(start_time))
when connect_by_isleaf = 1 then end_time - trunc(end_time)
else 1 end as duration_days
from dual
connect by level <= 1 + trunc(end_time) - trunc(start_time)
)
where duration_days != 0
order by event_id, day
;
The where clause is used when the end_time is midnight (at the beginning of an otherwise "new" day); in that case, presumably, you don't want to include that "new day" in the output, with a duration of 0 minutes.
In the lateral view, level = 1 corresponds to the first date in the interval, while connect_by_isleaf = 1 is for the last date in the interval. A special calculation is made when the end_time and start_time are on the same date. The query computes the difference in days first, then converts to minutes. Note that date calculations aren't 100% precise; I used round so I don't get results like 33.9999999999938020 minutes. If the inputs are in hh24:mi, we know beforehand that the answer (in minutes) should be an integer, so round seems fine there.

Time difference in correct format oracle

I want to difference between two time.
select
extract(hour from intrvl) as hh24,
extract(minute from intrvl) as mi
from
(select
to_timestamp_tz ('23:45','hh24:mi')
- to_timestamp_tz ('08:00','hh24:mi') as intrvl
from dual);
output-hh24-15
mi-45
Desired output:
hh24-08
mi-15
You can use a query like this
SELECT MOD (TRUNC (intrvl), 24) AS hours, (intrvl - TRUNC (intrvl)) * 60 AS minutes
FROM (SELECT 24 - ((TO_DATE ('23:45', 'hh24:mi') - TO_DATE ('08:00', 'hh24:mi')) * 24) AS intrvl
FROM DUAL);
If you want the part fo the day outside your time range - which is the only way I can see you'd get 08:15 - you can subtract your interval result from an interval of one day:
select
extract(hour from intrvl) as hh24,
extract(minute from intrvl) as mi
from (
select interval '1' day
- (to_timestamp_tz ('23:45','hh24:mi')
- to_timestamp_tz ('08:00','hh24:mi')) as intrvl
from dual
);
db<>fiddle

get data in 'n' hours interval between two dates oracle

i am trying to get data between two dates in an 'n' hour intervals ... the problem is that i am not getting desired result after 8 hour intervals ... my value in 'n' interval can range up to any number between 1 to 120.
Following is the Pseudo code of what i am tying to do:
-- i first select number of hours between two dates
SELECT
24 * (SYSDATE - to_date('2018-04-16 15:20', 'YYYY-MM-DD hh24:mi')) AS diff_hours
FROM dual;
-- Then i use the above value in CONNECT BY ROWNUM <= ROUND((hours between two dates/n),0) to get data in n intervals
SELECT TRUNC(sysdate - (rownum/ROUND((24/n),0)),'HH24') as the_hour
FROM dual
CONNECT BY ROWNUM <= ROUND((hours between two dates/n),0) ;
Sample query
SELECT
24 * (SYSDATE - to_date('2018-04-16 15:20', 'YYYY-MM-DD hh24:mi')) AS diff_hours
FROM dual;
SELECT TRUNC(sysdate - (rownum/ROUND((24/8),0)),'HH24') as the_hour
FROM dual
CONNECT BY ROWNUM <= ROUND((724/8),0) ;
How can i change above query to get data in 'n' hour intervals between two dates, with n being any number of hours?
Remove the first ROUND() in your SELECT
SELECT TRUNC (SYSDATE - (ROWNUM / (24 / 9)), 'HH24') AS the_hour
FROM DUAL
CONNECT BY ROWNUM <= ROUND ( (724 / 9), 0);
try this,
SELECT TO_DATE(:p_date1, 'MM/DD/YYYY') + (FLOOR((rownum*:p_interval)/24) + (MOD((rownum*:p_interval), 24)/24)) dt
FROM DUAL
CONNECT BY (rownum*:p_interval) <= ((TO_DATE(:p_date2, 'MM/DD/YYYY')+.5) - TO_DATE(:p_date1, 'MM/DD/YYYY') + (MOD((rownum*:p_interval), 24)/24)) * 24
ORDER BY 1;

Oracle subtracting days and minutes

I want to subtract "X" days and "X" minutes from sysdate, where the days and minutes are an integer as input parameter. For instance, 10 days and 5 minutes.
I found many examples to subtract either minutes or hours but not a combination of days and minutes.
select sysdate - 5 / 24 / 60 from dual -- will retrieve sysdate minus 5 minutes.
--What about the days?
Thank you!
Use an interval literal:
SELECT SYSDATE - INTERVAL '10 00:05' DAY(2) TO MINUTE
FROM DUAL
Or:
SELECT SYSDATE - INTERVAL '10' DAY - INTERVAL '5' MINUTE
FROM DUAL
Or just use arithmetic:
SELECT SYSDATE - 10 /* Days */ - 5 / 24 /60 /* Minutes */
FROM DUAL
Or use NUMTODSINTERVAL:
SELECT SYSDATE - NUMTODSINTERVAL( 10, 'DAY' ) - NUMTODSINTERVAL( 5, 'MINUTE' )
FROM DUAL
You can use Interval day to minute - http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements003.htm#i38598
select sysdate - interval '1 00:05' day to minute from dual

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