Search code examples
sqldb2window-functionsgaps-and-islands

How to summarize days by a flag field?


How can I summarize the days Kyle has on this table using a flag field?

Row Name Flag Days
1 Kyle 0 12
2 Kyle 0 02
3 Kyle 1 01
4 Kyle 1 18
5 Kyle 1 01
6 Kyle 0 01
7 Kyle 1 01
8 Kyle 1 01

I want this result:

Row Name Flag Days
1 Kyle 0 12
2 Kyle 0 02
3 Kyle 1 20
6 Kyle 0 01
7 Kyle 1 02

Solution

  • This reads like a gaps-and-island problem. If I follow this correctly, we can identify "adjacent" rows with the difference between row numbers, then aggregate islands whose flag is enabled:

    select min(row) as row, name, flag, sum(days) as days
    from (
        select t.*,
            row_number() over(partition by name order by row) rn1,
            row_number() over(partition by name, flag order by row) rn2
        from mytable t
    ) t
    group by name, flag, 
        case when flag = 1 then rn1 - rn2 else row end
    order by 1
    

    Demo on DB Fiddle (credits to nbk for creating the use case).