Create a table of time series data
create table time_data as
select * from (
select date'2022-08-01'
+ numtodsinterval ( level , 'minute' )
+ ( mod ( level, 17 ) / 60 / 24 )
+ ( sin ( level ) / 24 ) datetime
from dual
connect by level <= 200
union all
select date'2022-08-02'
+ ( level / 4 )
+ ( sin ( level ) / 24 ) datetime
from dual
connect by level <= 100
)
where datetime >= date'2022-08-01'
and datetime not between date'2022-08-01' + 15/24/60 and date'2022-08-01' + 19/24/60
order by datetime
Table created.
alter session set nls_date_format = 'DD-MON-YYYY HH24:MI'
Statement processed.
Group rows in 5-minute intervals
with rws as (
select trunc ( datetime ) dy,
trunc ( datetime, 'mi' ) mins,
5 / 1440 time_interval
from time_data
), intervals as (
select dy + (
floor ( ( mins - dy ) / time_interval ) * time_interval
) start_datetime
from rws
)
select start_datetime, count(*) from intervals
group by start_datetime
order by start_datetime
fetch first 5 rows only
START_DATETIME | COUNT(*) | 01-AUG-2022 00:00 | 3 | 01-AUG-2022 00:05 | 1 | 01-AUG-2022 00:10 | 5 | 01-AUG-2022 00:20 | 3 | 01-AUG-2022 00:25 | 5 |
---|
Group rows in 10-minute intervals
select trunc ( datetime ) + (
floor (
( trunc ( datetime, 'mi' ) - trunc ( datetime ) )
* 1440 / 10
) * 10 / 1440
) start_datetime,
count (*)
from time_data
group by trunc ( datetime )
+ ( floor (
( trunc ( datetime, 'mi' ) - trunc ( datetime ) )
* 1440 / 10
) * 10 / 1440
)
order by start_datetime
fetch first 5 rows only
START_DATETIME | COUNT(*) | 01-AUG-2022 00:00 | 4 | 01-AUG-2022 00:10 | 5 | 01-AUG-2022 00:20 | 7 | 01-AUG-2022 00:30 | 7 | 01-AUG-2022 00:40 | 3 |
---|
Group rows in N-minute intervals
declare
duration_in_minutes integer := 5;
begin
for rws in (
with rws as (
select trunc ( datetime ) dy,
trunc ( datetime, 'mi' ) mins,
duration_in_minutes / 1440 time_interval
from time_data
), intervals as (
select dy + (
floor ( ( mins - dy ) / time_interval ) * time_interval
) start_datetime
from rws
)
select start_datetime, count(*) row#
from intervals
group by start_datetime
order by start_datetime
fetch first 5 rows only
) loop
dbms_output.put_line ( rws.start_datetime || ' - ' || rws.row# );
end loop;
end;
Statement processed.
01-AUG-2022 00:00 - 3
01-AUG-2022 00:05 - 1
01-AUG-2022 00:10 - 5
01-AUG-2022 00:20 - 3
01-AUG-2022 00:25 - 5
Group rows in 5-minute intervals including missing times
declare
duration_in_minutes integer := 5;
start_time varchar2(20) := '01-AUG-2022 00:00';
number_of_intervals integer := 12;
begin
for rws in (
with times as (
select to_date ( start_time, 'DD-MON-YYYY HH24:MI' )
+ ( ( level - 1 ) * duration_in_minutes / 1440 ) dt
from dual
connect by level <= number_of_intervals
), intervals as (
select dt start_date,
dt + ( duration_in_minutes / 1440 ) end_date
from times
)
select start_date, end_date, count ( datetime ) row#
from intervals i
left join time_data t
on start_date <= datetime
and datetime < end_date
group by start_date, end_date
order by start_date
fetch first 5 rows only
) loop
dbms_output.put_line ( rws.start_date || ' - ' || rws.row# );
end loop;
end;
Statement processed.
01-AUG-2022 00:00 - 3
01-AUG-2022 00:05 - 1
01-AUG-2022 00:10 - 5
01-AUG-2022 00:15 - 0
01-AUG-2022 00:20 - 3
Group rows in N-minute intervals starting from source data
declare
duration_in_minutes integer := 5;
number_of_intervals integer := 12;
begin
for rws in (
with start_date as (
select min ( datetime ) start_date,
duration_in_minutes / 1440 time_interval
from time_data
), intervals as (
select start_date + ( ( level - 1 ) * time_interval ) start_date,
start_date + ( ( level ) * time_interval ) end_date
from start_date
connect by level <= number_of_intervals
)
select start_date, count ( datetime ) row#
from intervals
left join time_data
on start_date <= datetime
and datetime < end_date
group by start_date
order by start_date
) loop
dbms_output.put_line ( rws.start_date || ' - ' || rws.row# );
end loop;
end;
Statement processed.
01-AUG-2022 00:01 - 3
01-AUG-2022 00:06 - 2
01-AUG-2022 00:11 - 4
01-AUG-2022 00:16 - 2
01-AUG-2022 00:21 - 2
01-AUG-2022 00:26 - 4
01-AUG-2022 00:31 - 3
01-AUG-2022 00:36 - 3
01-AUG-2022 00:41 - 2
01-AUG-2022 00:46 - 3
01-AUG-2022 00:51 - 7
01-AUG-2022 00:56 - 4
Group rows in N-minute intervals with variable gaps
declare
duration_in_minutes integer := 5;
begin
for rws in (
select *
from time_data
match_recognize (
order by datetime
measures
init.datetime as interval_start,
init.datetime
+ numtodsinterval ( duration_in_minutes, 'minute' ) as interval_end,
count(*) as row#
pattern ( init time_interval* )
define
time_interval as datetime <
init.datetime + numtodsinterval ( duration_in_minutes, 'minute' )
)
fetch first 5 rows only
) loop
dbms_output.put_line ( rws.interval_start || ' - ' || rws.row# );
end loop;
end;
Statement processed.
01-AUG-2022 00:01 - 3
01-AUG-2022 00:06 - 2
01-AUG-2022 00:13 - 4
01-AUG-2022 00:20 - 4
01-AUG-2022 00:26 - 4
Combine all rows within N-minutes of the previous row
declare
duration_in_minutes integer := 5;
begin
for rws in (
select *
from time_data
match_recognize (
order by datetime
measures
init.datetime as interval_start,
init.datetime
+ numtodsinterval ( duration_in_minutes, 'minute' ) as interval_end,
count(*) as row#
pattern ( init time_interval* )
define
time_interval as datetime <
prev ( datetime ) + numtodsinterval ( duration_in_minutes, 'minute' )
)
fetch first 5 rows only
) loop
dbms_output.put_line ( rws.interval_start || ' - ' || rws.row# );
end loop;
end;
Statement processed.
01-AUG-2022 00:01 - 9
01-AUG-2022 00:20 - 11
01-AUG-2022 00:37 - 5
01-AUG-2022 00:49 - 23
01-AUG-2022 01:14 - 120