Skip to Main Content
  • Questions
  • Recursive query to calculate salary increases

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question.

Asked: July 21, 2022 - 7:48 am UTC

Last updated: July 26, 2022 - 1:38 pm UTC

Version: 11

Viewed 1000+ times

You Asked

Please tell me what condition of the problem can be thought up so that it can be solved only by recursion, not connect by. For example, you can do something like There is a list of employees, the coefficient of salary increase every year, his current salary For each of them, draw up a schedule for 20 years ahead of salaries, given that if the total salary of the entire department exceeds a million, then 10% is subtracted from each salary, and 10% is added to this million

My table
create table scrubs5(name varchar2(100),cent number, salary number);
insert into scrubs5
values ('John Dorian' ,10,50000);
insert into scrubs5
values ('Eliot Reed',15 ,40000);
insert into scrubs5
values ('Pesivald Cox',10, 35000);
insert into scrubs5
values ('Bob Kelso' ,20,30000);
insert into scrubs5
values ('Cris Terk',15, 25000);


Code

WITH data( sal, name, n, cent) AS (
SELECT  salary as sal, name, 1 as n, cent
FROM scrubs5
UNION ALL
SELECT  sal + sal*cent/100, name, n+1, cent
FROM data 
WHERE n < 5
),
data1(sal, name, n, cent, t) as
(SELECT sal, name, n, cent, 100000 as t FROM data
union all 
select case when sum(sal) over (partition by n)> t then sal- sal*cent/100 else sal end, name,n+1, cent, case when sum(sal) over (partition by n)> t then t+t*10/100 else t end
from data1 
WHERE n < 5)
select sal, name, n, cent, t from data1
order by n
;

and Chris said...

I'm a little unclear what you're asking here.

it can be solved only by recursion, not connect by

CONNECT BY is a recursive query!

If you're asking what problems must you use recursive WITH for instead of CONNECT BY, arguably both can do the same things. There are some classes of problems you'd need to combine CONNECT BY with other clauses that you can do purely using recursive WITH though.

Cases like these include:

The running product (repeated multiplication) - you can get close summing logarithms, but this has rounding errors
Running totals that change or reset based on arbitrary critiera - e.g. when the counter > 100, reset back to zero

The problem you've described has both of these properties:

Percentage increases/decreases are a form of repeated multiplication
The percentage change varies based on the values of other expressions for the current row

In terms of solving the problem you've asked, I'm guessing something like this should work:

with data( sal, name, n, cent) as (
  select salary as sal, name, 1 as n, cent
  from   scrubs5
), data1 ( sal, new_sal, name, n, cent, t ) as(
  select sal, sal new_sal, name, n, cent, 1000000 as t 
  from   data
  union all 
  select sal,
         case 
           when sum(new_sal) over (partition by n) < t 
           then round ( new_sal * ( 1 + ( cent / 100 ) ) )
           else round ( new_sal * 0.9 )
         end, 
         name, n+1, cent,
         case 
           when sum(new_sal) over (partition by n) < t 
           then t
           else t * 1.10
         end t
  from   data1 
  where  n < 20
)
select new_sal, name, n, cent, t, 
       sum ( new_sal ) over ( partition by n ) year_tot
from   data1
order  by n, name;

   NEW_SAL NAME                          N       CENT          T   YEAR_TOT
---------- -------------------- ---------- ---------- ---------- ----------
     30000 Bob Kelso                     1         20    1000000     180000
     25000 Cris Terk                     1         15    1000000     180000
     40000 Eliot Reed                    1         15    1000000     180000
     50000 John Dorian                   1         10    1000000     180000
     35000 Pesivald Cox                  1         10    1000000     180000
     36000 Bob Kelso                     2         20    1000000     204250
     28750 Cris Terk                     2         15    1000000     204250
     46000 Eliot Reed                    2         15    1000000     204250
     55000 John Dorian                   2         10    1000000     204250
     38500 Pesivald Cox                  2         10    1000000     204250
...     
    374394 Bob Kelso                    18         20    1210000    1090416
    164777 Cris Terk                    18         15    1210000    1090416
    263638 Eliot Reed                   18         15    1210000    1090416
    169180 John Dorian                  18         10    1210000    1090416
    118427 Pesivald Cox                 18         10    1210000    1090416
    449273 Bob Kelso                    19         20    1210000    1258319
    189494 Cris Terk                    19         15    1210000    1258319
    303184 Eliot Reed                   19         15    1210000    1258319
    186098 John Dorian                  19         10    1210000    1258319
    130270 Pesivald Cox                 19         10    1210000    1258319
    404346 Bob Kelso                    20         20    1331000    1132488
    170545 Cris Terk                    20         15    1331000    1132488
    272866 Eliot Reed                   20         15    1331000    1132488
    167488 John Dorian                  20         10    1331000    1132488
    117243 Pesivald Cox                 20         10    1331000    1132488


Is this answer out of date? If it is, please let us know via a Comment

More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.