В oracle вашу задачу можно решить при помощи оператора
model:
-- данные для выборки
with data as (
select 1 as id, 2009 as year, 3 as month, 50 as count from dual union all
select 2 as id, 2009 as year, 4 as month, 100 as count from dual union all
select 3 as id, 2009 as year, 5 as month, 133 as count from dual union all
select 4 as id, 2009 as year, 7 as month, 2 as count from dual union all
select 5 as id, 2010 as year, 2 as month, 98 as count from dual union all
select 6 as id, 2010 as year, 4 as month, 600 as count from dual
)
-- сам запрос
select year, month, count, round(result, 2) as increment_rate
from data
model
-- генерируем порядковый номер для строк,
-- по которому будем осуществлять доступ к данным
dimension by (row_number() over (order by year, month) rn)
-- указываем столбцы, которые будут отображаться/участвовать в расчетах
-- также добавляем несуществующий столбец result,
-- что бы в дальнейшем помещать в него результат вычислений
measures (count, year, month, 0 result)
rules (
-- делаем соответствующие вычисления
result[any] = greatest(decode(nvl(count[cv(rn)-1],0), 0, 0, count[cv(rn)] / count[cv(rn)-1])*100 - 100, 0)
)
Результат:
+------+-------+-------+---------------+
| YEAR | MONTH | COUNT | INCREMENT_RATE|
+------+-------+-------+---------------+
| 2009 | 3 | 50 | 0 |
+------+-------+-------+---------------+
| 2009 | 4 | 100 | 100 |
+------+-------+-------+---------------+
| 2009 | 5 | 133 | 33 |
+------+-------+-------+---------------+
| 2009 | 7 | 2 | 0 |
+------+-------+-------+---------------+
| 2010 | 2 | 98 | 4800 |
+------+-------+-------+---------------+
| 2010 | 4 | 600 | 512,24 |
+------+-------+-------+---------------+
Пояснения к формуле:
result[any] = greatest(decode(nvl(count[cv(rn)-1],0), 0, 0, count[cv(rn)] / count[cv(rn)-1])*100 - 100, 0)
Слева от знака равно мы указываем, что для каждой ячейки (ключевое слово
any ) в столбце
result в качестве значения мы рассчитываем выражение справа от знака равно.
Для того, что бы рассчитать величину
прироста, необходимо взять значение за текущий временной период, разделить его на значение за предыдущий временной период, затем умножить на 100% и вычесть 100%.
Но так как у нас для первого периода в таблице (для первой строки), нет предыдущего периода, а также значением в предыдущем периоде может быть 0, то возникает ошибка деления на 0. Поэтому нужно эту ситуацию обработать, для чего в формуле используется
decode, который проверяет, если значение предыдущего периода не существует или равно 0, тогда необходимо возвратить 0, если же значение предыдущего периода не равно 0, то рассчитываем отношение. Также используется функция
greatest, для того, чтобы вместо отрицательных значений отображать 0 (когда результат предыдущего периода больше текущего, соответственно прироста нет).
Если вместо прироста необходимо рассчитать процент роста, то вычитание 100% нужно убрать.