sqloracle-databaseanalytical

Multiply with Previous Value in Oracle SQL


Its easy to multiply (or sum/divide/etc.) with previous row in Excel spreadsheet, however, I could not do it so far in Oracle SQL.

A          B    C
199901   3.81   51905
199902  -6.09   48743.9855
199903   4.75   51059.32481
199904   6.39   54322.01567
199905  -2.35   53045.4483
199906   2.65   54451.15268
199907   1.1    55050.11536
199908  -1.45   54251.88869
199909   0      54251.88869
199910   4.37   56622.69622

Above, column B is static and column C has the formula as:
    ((B2/100)+1)*C1
    ((B3/100)+1)*C2
    ((B4/100)+1)*C3

Example: 51905 from row 1 multiplied with -6.09 from row 2: ((-6.09/100)+1)*51905

I have been trying analytical and window functions, but not succeeded yet. LAG function can give previous row value in current row, but cannot give calculated previous value.


Solution

  • This can be done with a help of MODEL clause

    select * 
    FROM (
         SELECT t.*,
           row_number() over (order by a) as rn
         from table1 t
    )
    MODEL
      DIMENSION BY (rn)
      MEASURES ( A, B,  0 c )
      RULES (
          c[rn=1] = 51905, -- value in a first row
          c[rn>1] = round( c[cv()-1] * (b[cv()]/100 +1), 6 )   
      )
      ;
    

    Demo: http://sqlfiddle.com/#!4/9756ed/11

    | RN |      A |     B |            C |
    |----|--------|-------|--------------|
    |  1 | 199901 |  3.81 |        51905 |
    |  2 | 199902 | -6.09 |   48743.9855 |
    |  3 | 199903 |  4.75 | 51059.324811 |
    |  4 | 199904 |  6.39 | 54322.015666 |
    |  5 | 199905 | -2.35 | 53045.448298 |
    |  6 | 199906 |  2.65 | 54451.152678 |
    |  7 | 199907 |   1.1 | 55050.115357 |
    |  8 | 199908 | -1.45 | 54251.888684 |
    |  9 | 199909 |     0 | 54251.888684 |
    | 10 | 199910 |  4.37 | 56622.696219 |