J'essaie de faire un calcul simple et de mettre à jour un champ en fonction des ID et des AsOfDates correspondants. Voici mon 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
La sous-requête fonctionne correctement et la logique semble correcte, mais SQL Server renvoie une erreur, indiquant que la clause FROM dans les instructions UPDATE et DELETE ne peut pas contenir de sources ou de jointures de sous-requête.
5 Réponses :
Essayez d'utiliser une sous-requête. Je pense que c'est la logique équivalente:
UPDATE Prices
SET Vol30Days = (SELECT STDEV(PX_BID)
FROM (SELECT TOP (31) p2.*
FROM Prices p2
WHERE p2.ID <= prices.ID
) p2
);
Merci Gordon! Je viens de l'essayer et j'ai obtenu ceci: l'identifiant en plusieurs parties "A.Vol30Days" ne pouvait pas être lié. Je peux le faire en utilisant une table intermédiaire, mais je cherchais quelque chose de plus élégant et plus facile à entretenir, comme Tim a fait allusion.
@CENDRE . . . Vous aviez cela sur votre question précédente.
Essayez d'utiliser un CTE pouvant être mis à jour:
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;
Mais étant donné que les nouvelles données ne sont qu'une quantité dérivée de la même table, vous voudrez peut-être éviter la mise à jour, car elle pourrait devoir être refait à chaque fois que les données de la table changent. Pensez plutôt à créer une vue.
Merci Tim, mais ma version de SQL Server ne prend pas en charge les CTE.
@ASH Alors je vous suggère sérieusement de mettre à jour votre version de SQL Server.
Utilisez un stockage intermédiaire, comme une variable de 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
Vous pouvez également utiliser une table temporelle:
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
Merci Marc. Je viens de l'essayer et j'ai obtenu ceci: Erreur d'analyse à la ligne: 1, colonne: 15: Syntaxe incorrecte près de «TABLE».
@ASH Cela devrait fonctionner. Êtes-vous certain d'utiliser SQL Server?. Quelle version?.
@ASH J'ai ajouté une alternative en utilisant une table temporelle
J'utilise Azure Data Warehouse. Cela semble être très, très similaire à SQL Server, mais je constate certaines différences à mesure que je m'approfondis de plus en plus.
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
Voici la documentation sur l'approche recommandée:
Veuillez noter que les clauses FROM avec JOIN - votre stratégie d'origine - sont actuellement en préversion privée et passeront bientôt en préversion publique.
Merci Ron. Merci tout le monde. Je suis prêt avec cette chose maintenant !!
. . SQL Server prend en charge les jointures dans la clause
FROM. Vous devez être plus précis sur la base de données que vous utilisez.