Create calculated value based on calculated value inside previous row
I'm trying to find a way to apply monthly percentage changes to forecast pricing. I set my problem up in excel to make it a bit more clear. I'm using SQL Server 2017.
We'll say all months before 9/1/18 are historical and 9/1/18 and beyond are forecasts. I need to calculate the forecast price (shaded in yellow on the sample data) using...
Forecast Price = (Previous Row Forecast Price * Pct Change) + Previous Row Forecast Price
Just to be clear, the yellow shaded prices do not exist in my data yet. That is what I am trying to have my query calculate. Since this is monthly percentage change, each row depends on the row before and goes beyond a single ROW_NUMBER/PARTITION solution because we have to use the previous calculated price. Clearly what is an easy sequential calculation in excel is a bit more difficult here. Any idea how to create forecasted price column in SQL?
sql sql-server tsql forecast
add a comment |
I'm trying to find a way to apply monthly percentage changes to forecast pricing. I set my problem up in excel to make it a bit more clear. I'm using SQL Server 2017.
We'll say all months before 9/1/18 are historical and 9/1/18 and beyond are forecasts. I need to calculate the forecast price (shaded in yellow on the sample data) using...
Forecast Price = (Previous Row Forecast Price * Pct Change) + Previous Row Forecast Price
Just to be clear, the yellow shaded prices do not exist in my data yet. That is what I am trying to have my query calculate. Since this is monthly percentage change, each row depends on the row before and goes beyond a single ROW_NUMBER/PARTITION solution because we have to use the previous calculated price. Clearly what is an easy sequential calculation in excel is a bit more difficult here. Any idea how to create forecasted price column in SQL?
sql sql-server tsql forecast
WHere is the first 150 coming from?
– Salman A
Nov 12 '18 at 19:04
150 = 50% * 100 + 100. Price from 1/1/18, plus the 50% price increase.
– BenM
Nov 12 '18 at 19:05
I believe you need to solve it with recursion. LAG/SUM OVER won't help here.
– Salman A
Nov 13 '18 at 6:05
add a comment |
I'm trying to find a way to apply monthly percentage changes to forecast pricing. I set my problem up in excel to make it a bit more clear. I'm using SQL Server 2017.
We'll say all months before 9/1/18 are historical and 9/1/18 and beyond are forecasts. I need to calculate the forecast price (shaded in yellow on the sample data) using...
Forecast Price = (Previous Row Forecast Price * Pct Change) + Previous Row Forecast Price
Just to be clear, the yellow shaded prices do not exist in my data yet. That is what I am trying to have my query calculate. Since this is monthly percentage change, each row depends on the row before and goes beyond a single ROW_NUMBER/PARTITION solution because we have to use the previous calculated price. Clearly what is an easy sequential calculation in excel is a bit more difficult here. Any idea how to create forecasted price column in SQL?
sql sql-server tsql forecast
I'm trying to find a way to apply monthly percentage changes to forecast pricing. I set my problem up in excel to make it a bit more clear. I'm using SQL Server 2017.
We'll say all months before 9/1/18 are historical and 9/1/18 and beyond are forecasts. I need to calculate the forecast price (shaded in yellow on the sample data) using...
Forecast Price = (Previous Row Forecast Price * Pct Change) + Previous Row Forecast Price
Just to be clear, the yellow shaded prices do not exist in my data yet. That is what I am trying to have my query calculate. Since this is monthly percentage change, each row depends on the row before and goes beyond a single ROW_NUMBER/PARTITION solution because we have to use the previous calculated price. Clearly what is an easy sequential calculation in excel is a bit more difficult here. Any idea how to create forecasted price column in SQL?
sql sql-server tsql forecast
sql sql-server tsql forecast
edited Nov 14 '18 at 6:41
Salman A
177k66337427
177k66337427
asked Nov 12 '18 at 18:49
jslater41jslater41
83
83
WHere is the first 150 coming from?
– Salman A
Nov 12 '18 at 19:04
150 = 50% * 100 + 100. Price from 1/1/18, plus the 50% price increase.
– BenM
Nov 12 '18 at 19:05
I believe you need to solve it with recursion. LAG/SUM OVER won't help here.
– Salman A
Nov 13 '18 at 6:05
add a comment |
WHere is the first 150 coming from?
– Salman A
Nov 12 '18 at 19:04
150 = 50% * 100 + 100. Price from 1/1/18, plus the 50% price increase.
– BenM
Nov 12 '18 at 19:05
I believe you need to solve it with recursion. LAG/SUM OVER won't help here.
– Salman A
Nov 13 '18 at 6:05
WHere is the first 150 coming from?
– Salman A
Nov 12 '18 at 19:04
WHere is the first 150 coming from?
– Salman A
Nov 12 '18 at 19:04
150 = 50% * 100 + 100. Price from 1/1/18, plus the 50% price increase.
– BenM
Nov 12 '18 at 19:05
150 = 50% * 100 + 100. Price from 1/1/18, plus the 50% price increase.
– BenM
Nov 12 '18 at 19:05
I believe you need to solve it with recursion. LAG/SUM OVER won't help here.
– Salman A
Nov 13 '18 at 6:05
I believe you need to solve it with recursion. LAG/SUM OVER won't help here.
– Salman A
Nov 13 '18 at 6:05
add a comment |
2 Answers
2
active
oldest
votes
You need to use a recursive CTE. That is one of the easier ways to look at the value of a calculated value from previous row:
DECLARE @t TABLE(Date DATE, ID VARCHAR(10), Price DECIMAL(10, 2), PctChange DECIMAL(10, 2));
INSERT INTO @t VALUES
('2018-01-01', 'ABC', 100, NULL),
('2018-01-02', 'ABC', 150, 50.00),
('2018-01-03', 'ABC', 130, -13.33),
('2018-01-04', 'ABC', 120, -07.69),
('2018-01-05', 'ABC', 110, -08.33),
('2018-01-06', 'ABC', 120, 9.09),
('2018-01-07', 'ABC', 120, 0.00),
('2018-01-08', 'ABC', 100, -16.67),
('2018-01-09', 'ABC', NULL, -07.21),
('2018-01-10', 'ABC', NULL, 1.31),
('2018-01-11', 'ABC', NULL, 6.38),
('2018-01-12', 'ABC', NULL, -30.00),
('2019-01-01', 'ABC', NULL, 14.29),
('2019-01-02', 'ABC', NULL, 5.27);
WITH ncte AS (
-- number the rows sequentially without gaps
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date) AS rn
FROM @t
), rcte AS (
-- find first row in each group
SELECT *, Price AS ForecastedPrice
FROM ncte AS base
WHERE rn = 1
UNION ALL
-- find next row for each group from prev rows
SELECT curr.*, CAST(prev.ForecastedPrice * (1 + curr.PctChange / 100) AS DECIMAL(10, 2))
FROM ncte AS curr
INNER JOIN rcte AS prev ON curr.ID = prev.ID AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte
ORDER BY ID, rn
Result:
| Date | ID | Price | PctChange | rn | ForecastedPrice |
|------------|-----|--------|-----------|----|-----------------|
| 2018-01-01 | ABC | 100.00 | NULL | 1 | 100.00 |
| 2018-01-02 | ABC | 150.00 | 50.00 | 2 | 150.00 |
| 2018-01-03 | ABC | 130.00 | -13.33 | 3 | 130.01 |
| 2018-01-04 | ABC | 120.00 | -7.69 | 4 | 120.01 |
| 2018-01-05 | ABC | 110.00 | -8.33 | 5 | 110.01 |
| 2018-01-06 | ABC | 120.00 | 9.09 | 6 | 120.01 |
| 2018-01-07 | ABC | 120.00 | 0.00 | 7 | 120.01 |
| 2018-01-08 | ABC | 100.00 | -16.67 | 8 | 100.00 |
| 2018-01-09 | ABC | NULL | -7.21 | 9 | 92.79 |
| 2018-01-10 | ABC | NULL | 1.31 | 10 | 94.01 |
| 2018-01-11 | ABC | NULL | 6.38 | 11 | 100.01 |
| 2018-01-12 | ABC | NULL | -30.00 | 12 | 70.01 |
| 2019-01-01 | ABC | NULL | 14.29 | 13 | 80.01 |
| 2019-01-02 | ABC | NULL | 5.27 | 14 | 84.23 |
Demo on DB Fiddle
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
add a comment |
In SQL Server you can access values of previous / next rows by using the windowing functions LAG and LEAD. You need to define the order of the rows by specifying it in the OVER clause. You may need to wrap the select query, that returns prev/next values in a derived table or CTE, and then select from it and calculate your forecasts.
with cte as (SELECT [Date], Price, LAG(Price, 1) over(order by [Date]) as PrevPrice from TABLE)
select [Date], Price, Price - PrevPrice as PriceChange from cte
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
If I got you point correctly, you need to add "partition by" in the over clauseLAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268337%2fcreate-calculated-value-based-on-calculated-value-inside-previous-row%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You need to use a recursive CTE. That is one of the easier ways to look at the value of a calculated value from previous row:
DECLARE @t TABLE(Date DATE, ID VARCHAR(10), Price DECIMAL(10, 2), PctChange DECIMAL(10, 2));
INSERT INTO @t VALUES
('2018-01-01', 'ABC', 100, NULL),
('2018-01-02', 'ABC', 150, 50.00),
('2018-01-03', 'ABC', 130, -13.33),
('2018-01-04', 'ABC', 120, -07.69),
('2018-01-05', 'ABC', 110, -08.33),
('2018-01-06', 'ABC', 120, 9.09),
('2018-01-07', 'ABC', 120, 0.00),
('2018-01-08', 'ABC', 100, -16.67),
('2018-01-09', 'ABC', NULL, -07.21),
('2018-01-10', 'ABC', NULL, 1.31),
('2018-01-11', 'ABC', NULL, 6.38),
('2018-01-12', 'ABC', NULL, -30.00),
('2019-01-01', 'ABC', NULL, 14.29),
('2019-01-02', 'ABC', NULL, 5.27);
WITH ncte AS (
-- number the rows sequentially without gaps
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date) AS rn
FROM @t
), rcte AS (
-- find first row in each group
SELECT *, Price AS ForecastedPrice
FROM ncte AS base
WHERE rn = 1
UNION ALL
-- find next row for each group from prev rows
SELECT curr.*, CAST(prev.ForecastedPrice * (1 + curr.PctChange / 100) AS DECIMAL(10, 2))
FROM ncte AS curr
INNER JOIN rcte AS prev ON curr.ID = prev.ID AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte
ORDER BY ID, rn
Result:
| Date | ID | Price | PctChange | rn | ForecastedPrice |
|------------|-----|--------|-----------|----|-----------------|
| 2018-01-01 | ABC | 100.00 | NULL | 1 | 100.00 |
| 2018-01-02 | ABC | 150.00 | 50.00 | 2 | 150.00 |
| 2018-01-03 | ABC | 130.00 | -13.33 | 3 | 130.01 |
| 2018-01-04 | ABC | 120.00 | -7.69 | 4 | 120.01 |
| 2018-01-05 | ABC | 110.00 | -8.33 | 5 | 110.01 |
| 2018-01-06 | ABC | 120.00 | 9.09 | 6 | 120.01 |
| 2018-01-07 | ABC | 120.00 | 0.00 | 7 | 120.01 |
| 2018-01-08 | ABC | 100.00 | -16.67 | 8 | 100.00 |
| 2018-01-09 | ABC | NULL | -7.21 | 9 | 92.79 |
| 2018-01-10 | ABC | NULL | 1.31 | 10 | 94.01 |
| 2018-01-11 | ABC | NULL | 6.38 | 11 | 100.01 |
| 2018-01-12 | ABC | NULL | -30.00 | 12 | 70.01 |
| 2019-01-01 | ABC | NULL | 14.29 | 13 | 80.01 |
| 2019-01-02 | ABC | NULL | 5.27 | 14 | 84.23 |
Demo on DB Fiddle
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
add a comment |
You need to use a recursive CTE. That is one of the easier ways to look at the value of a calculated value from previous row:
DECLARE @t TABLE(Date DATE, ID VARCHAR(10), Price DECIMAL(10, 2), PctChange DECIMAL(10, 2));
INSERT INTO @t VALUES
('2018-01-01', 'ABC', 100, NULL),
('2018-01-02', 'ABC', 150, 50.00),
('2018-01-03', 'ABC', 130, -13.33),
('2018-01-04', 'ABC', 120, -07.69),
('2018-01-05', 'ABC', 110, -08.33),
('2018-01-06', 'ABC', 120, 9.09),
('2018-01-07', 'ABC', 120, 0.00),
('2018-01-08', 'ABC', 100, -16.67),
('2018-01-09', 'ABC', NULL, -07.21),
('2018-01-10', 'ABC', NULL, 1.31),
('2018-01-11', 'ABC', NULL, 6.38),
('2018-01-12', 'ABC', NULL, -30.00),
('2019-01-01', 'ABC', NULL, 14.29),
('2019-01-02', 'ABC', NULL, 5.27);
WITH ncte AS (
-- number the rows sequentially without gaps
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date) AS rn
FROM @t
), rcte AS (
-- find first row in each group
SELECT *, Price AS ForecastedPrice
FROM ncte AS base
WHERE rn = 1
UNION ALL
-- find next row for each group from prev rows
SELECT curr.*, CAST(prev.ForecastedPrice * (1 + curr.PctChange / 100) AS DECIMAL(10, 2))
FROM ncte AS curr
INNER JOIN rcte AS prev ON curr.ID = prev.ID AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte
ORDER BY ID, rn
Result:
| Date | ID | Price | PctChange | rn | ForecastedPrice |
|------------|-----|--------|-----------|----|-----------------|
| 2018-01-01 | ABC | 100.00 | NULL | 1 | 100.00 |
| 2018-01-02 | ABC | 150.00 | 50.00 | 2 | 150.00 |
| 2018-01-03 | ABC | 130.00 | -13.33 | 3 | 130.01 |
| 2018-01-04 | ABC | 120.00 | -7.69 | 4 | 120.01 |
| 2018-01-05 | ABC | 110.00 | -8.33 | 5 | 110.01 |
| 2018-01-06 | ABC | 120.00 | 9.09 | 6 | 120.01 |
| 2018-01-07 | ABC | 120.00 | 0.00 | 7 | 120.01 |
| 2018-01-08 | ABC | 100.00 | -16.67 | 8 | 100.00 |
| 2018-01-09 | ABC | NULL | -7.21 | 9 | 92.79 |
| 2018-01-10 | ABC | NULL | 1.31 | 10 | 94.01 |
| 2018-01-11 | ABC | NULL | 6.38 | 11 | 100.01 |
| 2018-01-12 | ABC | NULL | -30.00 | 12 | 70.01 |
| 2019-01-01 | ABC | NULL | 14.29 | 13 | 80.01 |
| 2019-01-02 | ABC | NULL | 5.27 | 14 | 84.23 |
Demo on DB Fiddle
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
add a comment |
You need to use a recursive CTE. That is one of the easier ways to look at the value of a calculated value from previous row:
DECLARE @t TABLE(Date DATE, ID VARCHAR(10), Price DECIMAL(10, 2), PctChange DECIMAL(10, 2));
INSERT INTO @t VALUES
('2018-01-01', 'ABC', 100, NULL),
('2018-01-02', 'ABC', 150, 50.00),
('2018-01-03', 'ABC', 130, -13.33),
('2018-01-04', 'ABC', 120, -07.69),
('2018-01-05', 'ABC', 110, -08.33),
('2018-01-06', 'ABC', 120, 9.09),
('2018-01-07', 'ABC', 120, 0.00),
('2018-01-08', 'ABC', 100, -16.67),
('2018-01-09', 'ABC', NULL, -07.21),
('2018-01-10', 'ABC', NULL, 1.31),
('2018-01-11', 'ABC', NULL, 6.38),
('2018-01-12', 'ABC', NULL, -30.00),
('2019-01-01', 'ABC', NULL, 14.29),
('2019-01-02', 'ABC', NULL, 5.27);
WITH ncte AS (
-- number the rows sequentially without gaps
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date) AS rn
FROM @t
), rcte AS (
-- find first row in each group
SELECT *, Price AS ForecastedPrice
FROM ncte AS base
WHERE rn = 1
UNION ALL
-- find next row for each group from prev rows
SELECT curr.*, CAST(prev.ForecastedPrice * (1 + curr.PctChange / 100) AS DECIMAL(10, 2))
FROM ncte AS curr
INNER JOIN rcte AS prev ON curr.ID = prev.ID AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte
ORDER BY ID, rn
Result:
| Date | ID | Price | PctChange | rn | ForecastedPrice |
|------------|-----|--------|-----------|----|-----------------|
| 2018-01-01 | ABC | 100.00 | NULL | 1 | 100.00 |
| 2018-01-02 | ABC | 150.00 | 50.00 | 2 | 150.00 |
| 2018-01-03 | ABC | 130.00 | -13.33 | 3 | 130.01 |
| 2018-01-04 | ABC | 120.00 | -7.69 | 4 | 120.01 |
| 2018-01-05 | ABC | 110.00 | -8.33 | 5 | 110.01 |
| 2018-01-06 | ABC | 120.00 | 9.09 | 6 | 120.01 |
| 2018-01-07 | ABC | 120.00 | 0.00 | 7 | 120.01 |
| 2018-01-08 | ABC | 100.00 | -16.67 | 8 | 100.00 |
| 2018-01-09 | ABC | NULL | -7.21 | 9 | 92.79 |
| 2018-01-10 | ABC | NULL | 1.31 | 10 | 94.01 |
| 2018-01-11 | ABC | NULL | 6.38 | 11 | 100.01 |
| 2018-01-12 | ABC | NULL | -30.00 | 12 | 70.01 |
| 2019-01-01 | ABC | NULL | 14.29 | 13 | 80.01 |
| 2019-01-02 | ABC | NULL | 5.27 | 14 | 84.23 |
Demo on DB Fiddle
You need to use a recursive CTE. That is one of the easier ways to look at the value of a calculated value from previous row:
DECLARE @t TABLE(Date DATE, ID VARCHAR(10), Price DECIMAL(10, 2), PctChange DECIMAL(10, 2));
INSERT INTO @t VALUES
('2018-01-01', 'ABC', 100, NULL),
('2018-01-02', 'ABC', 150, 50.00),
('2018-01-03', 'ABC', 130, -13.33),
('2018-01-04', 'ABC', 120, -07.69),
('2018-01-05', 'ABC', 110, -08.33),
('2018-01-06', 'ABC', 120, 9.09),
('2018-01-07', 'ABC', 120, 0.00),
('2018-01-08', 'ABC', 100, -16.67),
('2018-01-09', 'ABC', NULL, -07.21),
('2018-01-10', 'ABC', NULL, 1.31),
('2018-01-11', 'ABC', NULL, 6.38),
('2018-01-12', 'ABC', NULL, -30.00),
('2019-01-01', 'ABC', NULL, 14.29),
('2019-01-02', 'ABC', NULL, 5.27);
WITH ncte AS (
-- number the rows sequentially without gaps
SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date) AS rn
FROM @t
), rcte AS (
-- find first row in each group
SELECT *, Price AS ForecastedPrice
FROM ncte AS base
WHERE rn = 1
UNION ALL
-- find next row for each group from prev rows
SELECT curr.*, CAST(prev.ForecastedPrice * (1 + curr.PctChange / 100) AS DECIMAL(10, 2))
FROM ncte AS curr
INNER JOIN rcte AS prev ON curr.ID = prev.ID AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte
ORDER BY ID, rn
Result:
| Date | ID | Price | PctChange | rn | ForecastedPrice |
|------------|-----|--------|-----------|----|-----------------|
| 2018-01-01 | ABC | 100.00 | NULL | 1 | 100.00 |
| 2018-01-02 | ABC | 150.00 | 50.00 | 2 | 150.00 |
| 2018-01-03 | ABC | 130.00 | -13.33 | 3 | 130.01 |
| 2018-01-04 | ABC | 120.00 | -7.69 | 4 | 120.01 |
| 2018-01-05 | ABC | 110.00 | -8.33 | 5 | 110.01 |
| 2018-01-06 | ABC | 120.00 | 9.09 | 6 | 120.01 |
| 2018-01-07 | ABC | 120.00 | 0.00 | 7 | 120.01 |
| 2018-01-08 | ABC | 100.00 | -16.67 | 8 | 100.00 |
| 2018-01-09 | ABC | NULL | -7.21 | 9 | 92.79 |
| 2018-01-10 | ABC | NULL | 1.31 | 10 | 94.01 |
| 2018-01-11 | ABC | NULL | 6.38 | 11 | 100.01 |
| 2018-01-12 | ABC | NULL | -30.00 | 12 | 70.01 |
| 2019-01-01 | ABC | NULL | 14.29 | 13 | 80.01 |
| 2019-01-02 | ABC | NULL | 5.27 | 14 | 84.23 |
Demo on DB Fiddle
answered Nov 13 '18 at 6:45
Salman ASalman A
177k66337427
177k66337427
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
add a comment |
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yea this works well. First time using recursion. However, if we apply this to a couple million rows I think processing will be extremely slow, correct?
– jslater41
Nov 13 '18 at 15:11
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
Yes it is iterative and difficult or perhaps impossible to optimize. Besides slowness, I am worried about recursion limit... SQL server stops after 32,768 iterations max.
– Salman A
Nov 13 '18 at 18:15
add a comment |
In SQL Server you can access values of previous / next rows by using the windowing functions LAG and LEAD. You need to define the order of the rows by specifying it in the OVER clause. You may need to wrap the select query, that returns prev/next values in a derived table or CTE, and then select from it and calculate your forecasts.
with cte as (SELECT [Date], Price, LAG(Price, 1) over(order by [Date]) as PrevPrice from TABLE)
select [Date], Price, Price - PrevPrice as PriceChange from cte
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
If I got you point correctly, you need to add "partition by" in the over clauseLAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
add a comment |
In SQL Server you can access values of previous / next rows by using the windowing functions LAG and LEAD. You need to define the order of the rows by specifying it in the OVER clause. You may need to wrap the select query, that returns prev/next values in a derived table or CTE, and then select from it and calculate your forecasts.
with cte as (SELECT [Date], Price, LAG(Price, 1) over(order by [Date]) as PrevPrice from TABLE)
select [Date], Price, Price - PrevPrice as PriceChange from cte
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
If I got you point correctly, you need to add "partition by" in the over clauseLAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
add a comment |
In SQL Server you can access values of previous / next rows by using the windowing functions LAG and LEAD. You need to define the order of the rows by specifying it in the OVER clause. You may need to wrap the select query, that returns prev/next values in a derived table or CTE, and then select from it and calculate your forecasts.
with cte as (SELECT [Date], Price, LAG(Price, 1) over(order by [Date]) as PrevPrice from TABLE)
select [Date], Price, Price - PrevPrice as PriceChange from cte
In SQL Server you can access values of previous / next rows by using the windowing functions LAG and LEAD. You need to define the order of the rows by specifying it in the OVER clause. You may need to wrap the select query, that returns prev/next values in a derived table or CTE, and then select from it and calculate your forecasts.
with cte as (SELECT [Date], Price, LAG(Price, 1) over(order by [Date]) as PrevPrice from TABLE)
select [Date], Price, Price - PrevPrice as PriceChange from cte
answered Nov 12 '18 at 19:01
Andrey NikolovAndrey Nikolov
3,7581621
3,7581621
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
If I got you point correctly, you need to add "partition by" in the over clauseLAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
add a comment |
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
If I got you point correctly, you need to add "partition by" in the over clauseLAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
Awesome. I'll try this later. One thing I didn't add in the sample data is multiple IDs over the same time span. I'm guessing this would be some sort of partition in the over statement or just a group by. I'll report back if I cant figure that part out.
– jslater41
Nov 12 '18 at 19:28
If I got you point correctly, you need to add "partition by" in the over clause
LAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
If I got you point correctly, you need to add "partition by" in the over clause
LAG(Price, 1) over(partition by ElementId order by [Date]) as PrevPriceForTheSameElementType
– Andrey Nikolov
Nov 12 '18 at 20:30
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53268337%2fcreate-calculated-value-based-on-calculated-value-inside-previous-row%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
WHere is the first 150 coming from?
– Salman A
Nov 12 '18 at 19:04
150 = 50% * 100 + 100. Price from 1/1/18, plus the 50% price increase.
– BenM
Nov 12 '18 at 19:05
I believe you need to solve it with recursion. LAG/SUM OVER won't help here.
– Salman A
Nov 13 '18 at 6:05