Reputation: 20352
I'm trying to do a simple calculation and update a field based on matching IDs and AsOfDates. Here is my script.
UPDATE A
SET A.Vol30Days =
(SELECT STDEV(PX_BID) OVER (ORDER BY ID, AsOfDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW)
FROM Prices)
FROM Prices A
INNER JOIN Prices B
ON A.ID = B.ID
AND A.AsOfDate = B.AsOfDate
The Subquery works fine and the logic looks ok, but SQL Server is throwing an error, saying FROM clause in UPDATE and DELETE statements cannot contain Subquery sources or joins.
Upvotes: 1
Views: 139
Reputation: 3078
Here's the documentation on the recommended approach:
Please note that FROM clauses with JOINs - your original strategy - are currently in private preview and will soon move to public preview.
Upvotes: 0
Reputation: 1271003
Try using a subquery. I think this is the equivalent logic:
UPDATE Prices
SET Vol30Days = (SELECT STDEV(PX_BID)
FROM (SELECT TOP (31) p2.*
FROM Prices p2
WHERE p2.ID <= prices.ID
) p2
);
Upvotes: 1
Reputation: 6465
Use an intermediate storage, like a table variable.
DECLARE @BIDS TABLE (ID integer, BIDS numeric(18,2))
INSERT INTO @BIDS (ID, BIDS)
SELECT A.ID, (SELECT STDEV(PX_BID) OVER (ORDER BY ID, AsOfDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) FROM Prices)
FROM Prices A
INNER JOIN Prices B ON A.ID = B.ID AND A.AsOfDate = B.AsOfDate
UPDATE A SET Vol30Days = B.BIDS
FROM Prices A
INNER JOIN @BIDS B ON B.ID = A.ID
Alternatively you can use a temporal table :
SELECT A.ID, (SELECT STDEV(PX_BID) OVER (ORDER BY ID, AsOfDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) FROM Prices) AS BIDS
INTO #BIDS
FROM Prices A
INNER JOIN Prices B ON A.ID = B.ID AND A.AsOfDate = B.AsOfDate
UPDATE A SET Vol30Days = B.BIDS
FROM Prices A
INNER JOIN #BIDS B ON B.ID = A.ID
DROP TABLE #BIDS
Upvotes: 0
Reputation: 1132
UPDATE A
SET A.Vol30Days = B.Vol30Days
FROM Prices A
INNER JOIN (
select t1.ID,
t1.AsOfDate,
STDEV(PX_BID) OVER (ORDER BY ID, AsOfDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) as Vol30Days
from Prices t1
) B
ON A.ID = B.ID
AND A.AsOfDate = B.AsOfDate
Upvotes: 0
Reputation: 522712
Try using an updatable CTE:
WITH cte AS (
SELECT Vol30Days AS VolOrig,
STDEV(PX_BID) OVER (ORDER BY ID, AsOfDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AS VolNew
FROM Prices
)
UPDATE cte
SET VolOrig = VolNew;
But given that the new data is just a derived quantity from the same table, you might want to avoid the update, since it might need to be redone any time the table's data changes. Instead, consider creating a view.
Upvotes: 1