SUM from previous ROW values
You can use the cumulative sum function (ANSI SQL):
with t as (
<your query here>
)
select t.*,
sum(receipt) over (order by date, shift) as totalreceipt,
sum(issue) over (order by date, shift) as totalissue,
sum(issue - receipt) over (order by date, shift) as variance
from t;
Cumulatively sum a portion of a previous value with its next value
I would use a for
loop to do this. It's important to initialize a vector first, especially if you're working with a large data set.
# initialize
newx <- vector("numeric", length(df$x))
newx[1] <- df$x[1]
for(i in 2:length(df$x)){
newx[i] <- df$x[i] + (0.8 * newx[i-1])
}
newx
# [1] 1.00000 2.80000 5.24000 8.19200 11.55360 15.24288 19.19430 23.35544 27.68435 32.14748
SQL query to calculate sum of row with previous row
SELECT t.date, (
SELECT SUM(numsubs)
FROM mytable t2
WHERE t2.date <= t.date
) AS cnt
FROM mytable t
Sum of previous rows and multiply with value from another column
While your post is lacking some vital information...I don't necessarily blame you because it's a difficult problem to both explain and to solve.
It looks like you're basically trying to come up with a compounding interest calculator. Except in this case, the rate changes every year.
To calculate the PRODUCT aggregate of your forecasts, I found this blog post:
https://blog.jooq.org/2018/09/21/how-to-write-a-multiplication-aggregate-function-in-sql/
It just required a very tiny bit of tweaking.
This is my answer:
DECLARE @StartingYear int = 2021,
@StartingBudget decimal(12, 2);
SELECT @StartingBudget = yt.budget
FROM #YourTable yt
WHERE yt.startyear = @StartingYear
SELECT yt.startyear, yt.division, yt.account, yt.budget, yt.forecast, YearBudget = yt.budget, PrevYearDiff = yt.budget
FROM #YourTable yt
WHERE yt.startyear = @StartingYear
UNION ALL
SELECT x.startyear, x.division, x.account, x.budget, x.forecast
, YearBudget = CONVERT(decimal(10,2), x.SumProdBudget)
, PrevYearDiff = CONVERT(decimal(10,2), x.SumProdBudget - LAG(x.SumProdBudget,1,@StartingBudget) OVER (ORDER BY x.startyear))
FROM (
SELECT yt.startyear, yt.division, yt.account, yt.budget, yt.forecast
, SumProdBudget = EXP(SUM(LOG(1+yt.forecast)) OVER (ORDER BY yt.startyear)) * @StartingBudget
FROM #YourTable yt
WHERE yt.startyear > @StartingYear
) x
Returns:
| startyear | division | account | budget | forecast | YearBudget | PrevYearDiff |
|-----------|----------|---------|------------|-------------|------------|--------------|
| 2021 | 40 | 4100 | 5122952.22 | 0.012306656 | 5122952.22 | 5122952.22 |
| 2022 | 40 | 4100 | 0.00 | 0.011424198 | 5181477.84 | 58525.62 |
| 2023 | 40 | 4100 | 0.00 | 0.010431491 | 5235528.38 | 54050.54 |
| 2024 | 40 | 4100 | 0.00 | 0.009311863 | 5284280.90 | 48752.52 |
| 2025 | 40 | 4100 | 0.00 | 0.008324122 | 5328267.90 | 43987.00 |
| 2026 | 40 | 4100 | 0.00 | 0.007763793 | 5369635.47 | 41367.57 |
The key to this whole thing is this line:
SELECT SumProdBudget = EXP(SUM(LOG(1+yt.forecast)) OVER (ORDER BY yt.startyear)) * @StartingBudget
This is saying to return a running product of all previous forecasts, then multiply that by the original budget. This will produce the budget for each year, technically based on the budget of the previous year.
Then once you have that, I stuck it in a sub-query to find the difference between the year and its previous year.
Sample Data:
IF OBJECT_ID('tempdb..#YourTable','U') IS NOT NULL DROP TABLE #YourTable; --SELECT * FROM #YourTable
CREATE TABLE #YourTable (
startyear int NOT NULL,
division int NOT NULL,
account int NOT NULL,
budget decimal(12, 2) NOT NULL,
forecast decimal(10, 9) NOT NULL,
);
INSERT INTO #YourTable (startyear, division, account, budget, forecast)
VALUES (2021, 40, 4100, 5122952.22, 0.012306656)
, (2022, 40, 4100, 0 , 0.011424198)
, (2023, 40, 4100, 0 , 0.010431491)
, (2024, 40, 4100, 0 , 0.009311863)
, (2025, 40, 4100, 0 , 0.008324122)
, (2026, 40, 4100, 0 , 0.007763793)
, (2027, 40, 4100, 0 , 0.007557735)
, (2028, 40, 4100, 0 , 0.007357883)
, (2029, 40, 4100, 0 , 0.007160051)
, (2030, 40, 4100, 0 , 0.006953345)
, (2031, 40, 4100, 0 , 0.006737952)
, (2032, 40, 4100, 0 , 0.006535297)
, (2033, 40, 4100, 0 , 0.006364179)
, (2034, 40, 4100, 0 , 0.006213237)
, (2035, 40, 4100, 0 , 0.006085724)
, (2036, 40, 4100, 0 , 0.005944279)
, (2037, 40, 4100, 0 , 0.005758285)
, (2038, 40, 4100, 0 , 0.005559474)
, (2039, 40, 4100, 0 , 0.005360105)
, (2040, 40, 4100, 0 , 0.005163794)
, (2041, 40, 4100, 0 , 0.004972228);
Sum of values from previous row columns + value of current row
In SQL Server 2008, you can use cross apply
:
select t.*, tt.GSumABC
from t cross apply
(select sum(valueA + valueB + ValueC) as GSumABC
from t t2
where t2.id <= t.id
) tt;
You can also phrase this as a correlated subquery:
select t.*,
(select sum(valueA + valueB + ValueC) as GSumABC
from t t2
where t2.id <= t.id
) as GSumABC
from t;
Related Topics
Mysql: Returning Multiple Columns from an In-Line Subquery
How Do We Implement an Is-A Relationship
How to Change a Table Name Using an SQL Query
How to Select and Update Rows at the Same Time
Set Database from Single User Mode to Multi User
Find Duplicate Records in a Table Using SQL Server
Is There Any Difference Between "!=" and "<>" in Oracle SQL
How to Combine 2 Select Statements into One
Multiple Full Outer Join on Multiple Tables
SQL Left Join First Match Only
SQL Query to Collapse Duplicate Values by Date Range
Store Select Query's Output in One Array in Postgres
Query to Check Index on a Table
Difference Between Different Types of SQL
Inserting Text String with Hex into Postgresql as a Bytea
Finding Rows with Same Values in Multiple Columns
MySQL Mulitple Row Insert-Select Statement with Last_Insert_Id()