I have two tables
WAC table
ID wac_inc item
-- ----------------- ----
1 2.310000000000000 A
2 1.100000000000000 A
3 2.130000000000000 A
4 1.340000000000000 A
Baseline Table
item baseline
---- ------------------
A 10.000000000000000
Expected Result
ID wac_inc item Running_Mul
-- ----------------- ---- -----------
1 2.310000000000000 A 10.231 -- 10 * (1+(2.310000000000000/100))
2 1.100000000000000 A 10.343541 -- 10.231 * (1+(1.100000000000000/100))
3 2.130000000000000 A 10.563858 -- 10.343541 * (1+(2.130000000000000/100))
4 1.340000000000000 A 10.705413 -- 10.563858 * (1+(1.340000000000000/100))
Formula to find running_mul
is
Baseline * (1 + (wac_inc/100))
here for every row previous row Running_Mul
value is the baseline
and for the first row baseline
will be coming from baseline table
.
Hope i made it clear. AFAIK we can do this using CURSOR
but i want to avoid RBAR
as much as possible.
Can anyone suggest me the better way of doing it.
You can transform a series of multiplications into a series of additions with the following math trick:
So
MUL(a)
isEXP(SUM(LOG(a)))
.This emits
sum = 10, product = 24
.Potential problems are rounding errors and zero factors.
You can now use one of the usual ways to achieve a running aggregate such as windowing functions. That's a solved problem.
you could do it easily with a recursive cte:
Output:
check in the demo
EDIT - Adding another solution:
you can do it by taking help from a copy of your original table :
Assuming your schema and data is:
1.take a copy from original table(use a
temp table
or atable variable
) and update the first record from baseline table:2.declare these variables:
3.update the copy:
and now you can check the result:
Result:
For the sake of completeness here is a full solution for SQL Server 2012 that uses the
EXP(SUM(LOG(val)))
trick suggested by @usr in another answer.result set
If SQL Server 2012 is available, this window
SUM
is very efficient. For previous versions any set-based solution would result inO(n*n)
complexity, which means that cursor would be a better way. Here is a very good article by Aaron Bertrand comparing different methods of calculating running totals: http://sqlperformance.com/2012/07/t-sql-queries/running-totals Or SO question: Calculate running total / running balanceOf course, if your table is small, then set-based solution with
O(n*n)
complexity may run faster thanO(n)
solution with the cursor due to cursor overhead, so you need to check the performance with your real data.Try:
Output:
EDIT1
I was trying to implement LOG EXP trick but could not manage unless @usr lead me to solution. So all credits to user @usr:
Or just:
if ID is the field you order by.
Output:
EDIT2
For SQL 2008 use:
EDIT3
Here is complete solution for SQL Server 2008 with dialing with NULLs and negative values: