Nous essayons de calculer une moyenne mobile et avons essayé de convertir de nombreuses réponses SO pour résoudre le problème. À ce stade, nous sums toujours infructueux.
Ce que nous avons essayé :
Voici quelques-unes des réponses SO que nous avons considérées.
Notre dernière tentative a été de modifier l'une des solutions (# 4) trouvées ici. https://www.red-gate.com/simple-talk/sql/t-sql-programming/calculating-values-within-a-window-in-transact-sql/
Exemple :
Voici un exemple dans SQL Fiddle: http://sqlfiddle.com/#!6/4570a/17
Dans le violon, nous essayons toujours de faire fonctionner correctement la SUM, mais finalement nous essayons d'get la moyenne.
L'objective final
En utilisant l'exemple Fiddle, nous devons find la différence entre Value1 et ComparisonValue1 et la présenter comme Diff1. Lorsqu'une ligne n'a pas de Value1 disponible, nous devons l'estimer en prenant la moyenne des deux dernières valeurs Diff1, puis l'append à ComparisonValue1 pour cette ligne.
Avec la requête correcte, le résultat ressemblerait à ceci:
GroupID Number ComparisonValue1 Diff1 Value1 5 10 54.78 2.41 57.19 5 11 55.91 2.62 58.53 5 12 55.93 2.78 58.71 5 13 56.54 2.7 59.24 5 14 56.14 2.74 58.88 5 15 55.57 2.72 58.29 5 16 55.26 2.73 57.99
Question : est-il possible de calculer cette moyenne quand elle pourrait potentiellement entrer dans la moyenne des lignes suivantes?
Mise à jour :
Le crédit pour l'idée va à cette réponse: https://stackoverflow.com/a/35152131/6305294 de @ JesúsLópez
J'ai inclus des commentaires dans le code pour l'expliquer.
METTRE À JOUR
Les résultats de la requête correspondent maintenant exactement à votre exemple de sortie.
;WITH cte AS ( -- This is similar to your ItemWithComparison view SELECT i.Number, i.Value1, i2.Value1 AS ComparisonValue1, -- Calculated Differences; NULL will be returned when i.Value1 is NULL CONVERT( DECIMAL( 10, 3 ), i.Value1 - i2.Value1 ) AS Diff FROM Item AS i LEFT JOIN [Group] AS G ON g.ID = i.GroupID LEFT JOIN Item AS i2 ON i2.GroupID = g.ComparisonGroupID AND i2.Number = i.Number WHERE NOT i2.Id IS NULL ), cte2 AS( /* Start with the first number Note if you do not have at least 2 consecutive numbers (in cte) with non-NULL Diff value and therefore Diff1Ago or Diff2Ago are NULL then everything else will not work; You may need to add additional logic to handle these cases */ SELECT TOP 1 -- start with the 1st number (see ORDER BY) a.Number, a.Value1, a.ComparisonValue1, a.Diff, b.Diff AS Diff1Ago FROM cte AS a -- "1 number ago" LEFT JOIN cte AS b ON a.Number - 1 = b.Number WHERE NOT a.Value1 IS NULL ORDER BY a.Number UNION ALL SELECT b.Number, b.Value1, b.ComparisonValue1, ( CASE WHEN NOT b.Value1 IS NULL THEN b.Diff ELSE CONVERT( DECIMAL( 10, 3 ), ( a.Diff + a.Diff1Ago ) / 2.0 ) END ) AS Diff, a.Diff AS Diff1Ago FROM cte2 AS a INNER JOIN cte AS b ON a.Number + 1 = b.Number ) SELECT *, ( CASE WHEN Value1 IS NULL THEN ComparisonValue1 + Diff ELSE Value1 END ) AS NewValue1 FROM cte2 OPTION( MAXRECURSION 0 );
Limitations: cette solution fonctionne bien uniquement lorsque vous devez prendre en count un petit nombre de valeurs précédentes.