I need to sum delay time in seconds for records that are same by value column. Problem is I need them only grouped by the same chunks and not all together. For example, for below data I would need sum of 3 records for value 3 and separately for 2 records further down, and not to sum records for value 4 as they are not together. Is there a way to do this?
ID Value Timestamp Delay(s) 166549627 4 19-OCT-21 11:00:19 11.4 166549450 8 19-OCT-21 11:00:27 7.5 166549446 3 19-OCT-21 11:00:34 7.1 166549625 3 19-OCT-21 11:00:45 10.9 166549631 3 19-OCT-21 11:00:58 13.3 166550549 3 19-OCT-21 11:01:03 4.5 166549618 7 19-OCT-21 11:01:14 8.8 166549627 4 19-OCT-21 11:01:23 11.4 166550549 3 19-OCT-21 11:01:45 4.5 166550549 3 19-OCT-21 11:01:59 4.5
CodePudding user response:
If you want to use PL/SQL you can loop over all records orderd by timestamp.
Just remember the last value und sum up if it is the same as the current value. If not, just save the sum somewehre else and continue.
You can also write this as a pipelined function to use a query to access the data.
declare l_sum number := 0; l_last_val number; begin for rec in (select * from your_table order by timestamp) loop if l_last_val = rec.value then l_sum := l_sum rec.delay; continue; elsif l_last_val is not null then dbms_output.put_line('value: ' || l_last_val || ' sum: ' || l_sum); -- save last_val and sum end if; l_last_val := rec.val; l_sum := rec.delay; end loop; dbms_output.put_line('value: ' || l_last_val || ' sum: ' || l_sum); -- save last_val and sum end;
CodePudding user response:
You don't even need to use plsql for that purpose. Only SQL can suffice. Below solution uses the recursive common table expression (CTE) technic to create sub groups according to value column and timestamp column.
with ranked_rows (ID, VALUE, TIMESTAMP, DELAY, RNB) as (
select ID, VALUE, TIMESTAMP, DELAY, row_number()over(order by TIMESTAMP) rnb
from YourTable
)
, cte (ID, VALUE, TIMESTAMP, DELAY, RNB, grp) as (
select ID, VALUE, TIMESTAMP, DELAY, RNB, 1 grp
from ranked_rows
where rnb = 1
union all
select t.ID, t.VALUE, t.TIMESTAMP, t.DELAY, t.RNB, case when c.VALUE = t.VALUE then c.grp else c.grp 1 end
from ranked_rows t
join cte c on c.rnb 1 = t.rnb
)
select VALUE, sum(DELAY) sum_consecutive_DELAY, min(TIMESTAMP) min_TIMESTAMP, max(TIMESTAMP) max_TIMESTAMP, count(*)nb_rows
from cte
group by VALUE, GRP
order by min_TIMESTAMP
;