简体   繁体   English

基于自加入的更新

[英]Update Based on Self-Join

I'm trying to do a simple calculation and update a field based on matching IDs and AsOfDates.我正在尝试做一个简单的计算并根据匹配的 ID 和 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.子查询工作正常,逻辑看起来正常,但 SQL Server 抛出错误,说 UPDATE 和 DELETE 语句中的 FROM 子句不能包含子查询源或连接。

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
                    );

Try using an updatable CTE:尝试使用可更新的 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.相反,请考虑创建一个视图。

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
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

Here's the documentation on the recommended approach:以下是有关推荐方法的文档:

https://docs.microsoft.com/en-us/sql/t-sql/queries/update-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15#ah-ansi-join-replacement-for-update-statements https://docs.microsoft.com/en-us/sql/t-sql/queries/update-transact-sql?redirectedfrom=MSDN&view=sql-server-ver15#ah-ansi-join-replacement-for-update-声明

  • Create a transient table with the results of the JOIN clause使用 JOIN 子句的结果创建一个临时表
  • Write the UPDATE referencing the transient table写入引用临时表的 UPDATE

Please note that FROM clauses with JOINs - your original strategy - are currently in private preview and will soon move to public preview.请注意,带有 JOIN 的 FROM 子句(您的原始策略)目前处于私人预览版中,很快将转为公共预览版。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM