Вот подход с использованием оконных функций:
select
usr,
revenue,
r_revenue running_revenue,
sum(case
when lag_r_revenue is null or r_revenue / divisor <> lag_r_revenue / divisor
then 1 else 0
end) over(order by revenue, usr) grp
from (
select t.*, lag(r_revenue) over(order by revenue, usr) lag_r_revenue
from (
select
t.*,
sum(revenue) over(order by revenue, usr) r_revenue,
sum(revenue) over() / 4 divisor
from mytable t
) t
) t
order by running_revenue
Самый внутренний подзапрос вычисляет текущую сумму revenue
(псевдоним r_revenue
); он также вычисляет целевой доход на группу путем деления общего дохода на 4.
Следующий уровень добавляет предыдущий текущий доход к каждой строке (lag_r_revenue
).
Наконец, внешний запрос создает суммы окон, которые увеличиваются каждый раз, когда (целочисленное) соотношение между текущей суммой и целевым значением для каждой группы изменяется.
Демонстрация в БД Скрипка :
usr | revenue | running_revenue | grp
--: | ------: | --------------: | --:
1 | 5 | 5 | 1
2 | 5 | 10 | 1
3 | 10 | 20 | 1
4 | 15 | 35 | 1
5 | 15 | 50 | 2
6 | 20 | 70 | 2
7 | 20 | 90 | 2
8 | 25 | 115 | 3
9 | 30 | 145 | 3
10 | 55 | 200 | 4