我的存储过程花费的时间太长,只是用另一列的值更新一列,但是从前一行的值更新(按INT排序,其次是STR)
我使用的代码:
DECLARE @ITERg INT;
SET @ITERg = 1
WHILE @ITERg < 6131
BEGIN
UPDATE Avg14RSI
SET Avg14GreenP = (SELECT TOP 1 Avg14Green
FROM Avg14RSI a
WHERE IDn = @ITERg AND a.IntDate < Avg14RSI.IntDate
ORDER BY a.IDn, a.Ticker, a.IntDate DESC)
WHERE IDn = @ITERg
SET @ITERg = @ITERg + 1
END;
如果有人可以帮助我,我将非常感激!谢谢!
答案 0 :(得分:2)
原来lag
函数非常有用:
UPDATE UpdateTarget
SET Avg14GreenP = Displaced
FROM (SELECT a.Avg14GreenP, LAG(a.Avg14Green) OVER (PARTITION BY a.Ticker
ORDER BY a.[Date]) AS Displaced
FROM Avg14RSI a) AS UpdateTarget;
答案 1 :(得分:1)
首先,看起来你真的有SQL Server 2014.令人困惑的是,第一个SQL Server 2014版本是版本号12.0.2000.8(SP1是12.whatever),这就是你看到12 *的原因。 SSMS和分析服务的版本。如果您完全不确定,只需执行SELECT @@VERSION
,您就可以获得有关SQL Server本身的完整信息。
即使你有SQL Server 2012也没关系,因为Martin Smith是正确的,{1}}和LAG
是在SQL Server 2012中引入的。
LEAD
可让您收集前一行的值(LAG
从下一行获取值)。这是一个快速演示,其中列出了员工的工资,其中包括最接近他们的工资但更少的工资(例如,Masood获得72,000,而Jen,他们紧随其后,获得68,000):
LEAD
所以你可以看到Jen的行包括Manaa的薪水,Masood的行包括Jen的薪水等等。没有比Manaa更低的薪水,因此该行显示前一薪水为NULL。
回到您的数据,您应该能够通过此查询获取CREATE TABLE Employees (
Name VARCHAR(20),
Salary NUMERIC(10,2));
GO
INSERT INTO Employees VALUES
('Fred', 80000),
('Manaa', 65000),
('Ulrika', 90000),
('Masood', 72000),
('Jen', 68000);
SELECT
Name,
Salary,
LAG(Salary) OVER (ORDER BY Salary) AS PriorSalary
FROM Employees
ORDER BY Name;
Name Salary PriorSalary
------ -------- -----------
Fred 80000.00 72000.00
Jen 68000.00 65000.00
Manaa 65000.00 NULL
Masood 72000.00 68000.00
Ulrika 90000.00 80000.00
中Avg14Green
之前ID
值的ID列表(我将尝试解释PARTITION
在查询之后):
SELECT
IDn,
LAG(Avg14Green) OVER (
PARTITION BY IDn
ORDER BY Ticker, IntDate DESC) AS PriorAvg14Green
FROM Avg14RSI;
PARTITION
表示在通过自动收报机和日期降序排序时获取先前的Avg14Green
,但仅对具有相同IDn
值的其他行执行此操作。
无论如何,请尝试查询,如果它具有您要查找的值,则可以将其用于一次性UPDATE
,而不是一次处理一个IDn
;它几乎可以保证更快:
UPDATE Avg14RSI
SET Avg14GreenP = pr.PriorAvg14Green
FROM Avg14RSI
JOIN (
SELECT
IDn,
LAG(Avg14Green) OVER (
PARTITION BY IDn
ORDER BY Ticker, IntDate DESC) AS PriorAvg14Green
FROM Avg14RSI
) pr ON Avg14RSI.IDn = pr.IDn;
请注意,Ticker, IntDate DESC
之前的最早一行NULL
为PriorAvg14Green
。我在这里有一点脑屁并且无法弄清楚你现有代码在这种情况下会做什么,所以如果你不想更新每个IDn
的第一行,只需添加一个上述查询的WHERE
子句省略了空pr.PriorAvg14Green
值:
... the query above, plus
WHERE pr.Avg14Green IS NOT NULL;