Search code examples
sqloracleoracle-sqldeveloperwindow-functionsgaps-and-islands

Oracle SQL - Running Sum based on group by and condition


I have table that looks like

ID      SEQ       LABEL     COUNT
1        1           0       3
1        2           0       2
1        3           0       6
1        4           1       2
1        5           0       3
1        6           0       5
2        1           0       2
2        2           1       1
2        3           0       3

I would like to create a column called running_count. It calculates cumulative sum of the column count till the Label is 1 and then reset and start cumulative sum again.

Expected Output:

ID      SEQ       LABEL1     COUNT1     RUNNING_COUNT
1        1           0       3              3
1        2           0       2              5
1        3           0       6              14
1        4           1       2              16
1        5           0       3              3
1        6           0       5              8
2        1           0       2              2
2        2           1       1              3
2        3           0       3              3

I tried the following query

SELECT A.*, SUM(COUNT1) over (partition by ID,LABEL1 order by SEQ) as RUNNING_COUNT FROM TABLE_1 A

The problem here is that the cumulative sum stops in previous row(Seq) for Label = 1. I need to get the running sum till Label = 1 for Each ID based on Seq.

The Wrong Output I am getting

ID      SEQ       LABEL1     COUNT1     RUNNING_COUNT
1        1           0       3              3
1        2           0       2              5
1        3           0       6              14
1        4           1       2              2
1        5           0       3              3
1        6           0       5              8
2        1           0       2              2
2        2           1       1              1
2        3           0       3              3

Solution

  • You could make a first window sum() to define the groups, then use it as partition for the outer query:

    select 
        t.*,
        sum(count1) over(partition by id, grp order by seq) running_count
    from (
        select 
            t.*,
            sum(label) over(partition by id order by seq desc) grp
        from mytable t
    ) t
    

    Demo on DB Fiddle:

    ID | SEQ | LABEL | COUNT1 | GRP | RUNNING_COUNT
    -: | --: | ----: | -----: | --: | ------------:
     1 |   1 |     0 |      3 |   1 |             3
     1 |   2 |     0 |      2 |   1 |             5
     1 |   3 |     0 |      6 |   1 |            11
     1 |   4 |     1 |      2 |   1 |            13
     1 |   5 |     0 |      3 |   0 |             3
     1 |   6 |     0 |      5 |   0 |             8
     2 |   1 |     0 |      2 |   1 |             2
     2 |   2 |     1 |      1 |   1 |             3
     2 |   3 |     0 |      3 |   0 |             3