我们正在尝试计算滚动平均值,并试图转换大量的SO答案来解决问题。到目前为止,我们仍然没有成功。
我们尝试了什么:
以下是我们考虑的一些SO答案。
我们最近的尝试是修改此处找到的解决方案之一(#4)。 https://www.red-gate.com/simple-talk/sql/t-sql-programming/calculating-values-within-a-rolling-window-in-transact-sql/
示例:
以下是SQL Fiddle中的一个示例:http://sqlfiddle.com/#!6/4570a/17
在小提琴中,我们仍然试图让SUM工作正常但最终我们试图获得平均值。
最终目标
使用小提琴示例,我们需要找到Value1和ComparisonValue1之间的区别,并将其显示为Diff1。当一行没有Value1可用时,我们需要通过取最后两个Diff1值的平均值来估算它,然后将其添加到该行的ComparisonValue1。
使用正确的查询,结果如下所示:
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
问题:是否可以计算此平均值,因为它可能会影响以下行的平均值?
更新:
答案 0 :(得分:0)
这个想法归功于这个答案:来自@JesúsLópez的https://stackoverflow.com/a/35152131/6305294
我在代码中包含了注释来解释它。
<强>更新强>
查询结果现在与您的示例输出完全匹配。
;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 );
限制: 只有在需要考虑少量先前值时,此解决方案才能正常工作。