Not getting full series multiplication (product) i

2019-07-21 11:34发布

问题:

I have a CONNECT BY query that I am not getting desired results from.

The final sub-query and query are supposed to produce the product of multiplying a string of percentages together.

It starts with a table of retained percentages (PCT) from year to year. As the query progresses, it's supposed to take the PCT from the first year and multiply it by the PCT from the next year and so on until it reaches the desired depth. The effect is supposed to be like multiplying down the diagonal in a cross-tab, where the YR (year) and yset represent the start row and column.

Instead of getting the full string as the query progresses, I am only getting the result of the last two percentages.

It may be a simple mistake, but extra eyes will help find it out more quickly.

Code:

     with recurreten as
(
select  YR, YSet, 
      rtnpct rtn_year, 
      level lvl, ' - ' s1,   
      rtnpct * nvl( prior rtnpct, 1)  rtnpct 
      --- Below here only for checking the paths
      , sys_connect_by_path( nvl(rtnpct, 1) , '/')  prodpath 
from Z_RETENTIONPCT
    connect by yr = prior yr+1 and yset  = prior yset+1
    start with YR = 1998  -- :StartYr
               and
               yset = 20  -- :StartYSet
)

-- final results
select yr, yset, 
      round(rtn_year * 100, 2 ) rtn_year,   
      lvl, -- years the Cumulative Continuation Rate is extended
      s1,  
      round(rtnpct, 2) CCR  
      --- Below here only for checking results
      , rtnpct CCRFull -- Extra digits, for math check
      , prodpath  -- Only used by us, to check the #'s feeding the CCR
from recurreten
where  lvl <= 10 -- :Depth     
order by yr, yset, lvl
;

I have set up an example in SQLFiddle at http://sqlfiddle.com/#!4/ce945/1/0
The example uses WITH to set up some dummy data.

Results examples would be: (desired results)

Year    Col     Reten_yr    Full prod    Full Prod Path
1998    20      0.84766     0.847660000  = 0.84766
1999    21      0.77941     0.660674681  = 0.84766 * 0.77941
2000    22      0.78659     0.519680097  = 0.84766 * 0.77941 * 0.78659
2001    23      0.76879     0.399524862  = 0.84766 * 0.77941 * 0.78659 * 0.76879

(current/wrong results)

Year    Col     Reten_yr    wrong prod   Partial Path
1998    20      0.84766     0.847660000  = 0.84766
1999    21      0.77941     0.660674681  = 0.84766 * 0.77941
2000    22      0.78659     0.613076112  =           0.77941 * 0.78659
2001    23      0.76879     0.604722526  =                     0.78659 * 0.76879

Why am I not getting the full (multiplication) product? What can I do to fix this? Anyone...? Anyone? Bueller?

UPDATE: Eat A Peach provided the fix necessary to get truly cumulative results. I had to update that example due to my hand-tailoring the sample data which hid the scope of the regular data: rows for 50+ years sequentially, with up to 70 YCS for each year. The updated query did sequential cumulative products and my requirement is "diagonally sequential cumulative products". I kept the log-addition solution and added the CONNECT BY back.

http://sqlfiddle.com/#!4/1c326/2

Shows some default values for starting points and depth.

Thanks again!

回答1:

What you need is cumulative multiplication. But there is no such function either as Aggregate or Analytical function. But maths tells us multiplication can be changed to addition using logarithm.

a * b =  exp(ln(a) + ln(b))

Use this in SUM as analytical function. No need to use CONNECT BY construct.

SQL Fiddle

recurreten as
(
select  YR, YSet, 
      rtnpct rtn_year, 
      round(exp(sum(ln(rtnpct)) over (order by yr, yset rows between unbounded preceding and current row)),2) ccr,
      exp(sum(ln(rtnpct)) over (order by yr, yset rows between unbounded preceding and current row)) ccrfull
from Z_RETENTIONPCT
)
select * from recurreten
order by yr, yset

Results:

|   YR | YSET | RTN_YEAR |  CCR |        CCRFULL |
|------|------|----------|------|----------------|
| 1998 |   20 |  0.84766 | 0.85 |        0.84766 |
| 1999 |   21 |  0.77941 | 0.66 |   0.6606746806 |
| 2000 |   22 |  0.78659 | 0.52 | 0.519680097013 |
| 2001 |   23 |  0.76879 |  0.4 | 0.399524861783 |
| 2002 |   24 |  0.80952 | 0.32 |  0.32342336611 |
| 2003 |   25 |  0.76316 | 0.25 | 0.246823776081 |
| 2004 |   26 |  0.82425 |  0.2 | 0.203444497435 |
| 2005 |   27 |   0.6992 | 0.14 | 0.142248392606 |
| 2006 |   28 |  0.77071 | 0.11 | 0.109632258666 |
| 2007 |   29 |    0.702 | 0.08 | 0.076961845583 |