Existe-t-il une méthode plus rapide pour mettre à jour une nouvelle colonne d'une autre colonne mais d'une rangée précédente?

Ma procédure stockée prend trop de time juste pour mettre à jour une colonne avec une valeur d'une autre colonne mais d'une valeur d'une rangée précédente (ordonnée par un INT et d'autre part une STR)

Le code que j'utilise:

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; 

Je serais vraiment reconnaissant si quelqu'un pouvait m'aider! Merci!

Tout d'abord, il semble que vous avez vraiment SQL Server 2014. Confusingly, la première version de SQL Server 2014 est le numéro de version 12.0.2000.8 (SP1 est 12.whatever), ce qui explique pourquoi vous voyez les versions 12. * pour SSMS et les services d'parsing. Si vous n'êtes pas du tout sûr, faites simplement une SELECT @@VERSION et vous obtiendrez toutes les informations sur SQL Server lui-même.

Même si vous avez SQL Server 2012, vous êtes OK car Martin Smith a raison de dire que LAG et LEAD ont été introduits dans SQL Server 2012.

LAG vous permet de rassembler les valeurs d'une ligne précédente ( LEAD obtient les valeurs de la ligne suivante). Voici une démo rapide qui dresse la list des employés avec leur salaire, et qui inclut le salaire le plus proche de leur salaire (par exemple, Masood fait 72 000 et Jen, juste derrière, en fait 68 000):

 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 

Vous pouvez donc voir que la rangée pour Jen comprend le salaire de Manaa, la ligne pour Masood inclut le salaire de Jen, etc. Il n'y a pas de salaire inférieur à celui de Manaa, donc cette ligne affiche NULL pour le salaire antérieur.

Pour revenir à vos données, vous devriez pouvoir get une list d'ID avec des valeurs Avg14Green antérieures dans l' ID avec cette requête (j'essaierai d'expliquer la PARTITION après la requête):

 SELECT IDn, LAG(Avg14Green) OVER ( PARTITION BY IDn ORDER BY Ticker, IntDate DESC) AS PriorAvg14Green FROM Avg14RSI; 

La PARTITION dit d'get le Avg14Green antérieur lors de la command par ticker et la date décroissante, mais seulement pour les autres lignes qui ont la même valeur IDn .

En tout cas, essayez la requête, et si elle a les valeurs que vous searchz, vous pouvez l'utiliser pour une mise à jour one-shot au lieu de traiter un IDn à la fois; c'est presque garanti d'être plus rapide:

 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; 

Rappelez-vous que la première ligne par Ticker, IntDate DESC aura NULL pour PriorAvg14Green . Je suis un peu pète de cerveau ici et ne peux pas comprendre ce que votre code existant va faire dans cette situation, donc au cas où vous ne voulez pas mettre à jour la première ligne pour chaque IDn append une clause WHERE à la ci-dessus requête pour omettre les valeurs null pr.PriorAvg14Green :

 ... the query above, plus WHERE pr.Avg14Green IS NOT NULL; 

Il s'avère que la fonction de lag est très utile:

 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;