Hive 的加权移动平均值 SQL

weighted moving average with Hive SQL

给定如下所示的 Hive table 我想计算加权移动平均值。在 table 中,1 是这种加权移动平均线的示例。每列的值为

col_value = (1 * n) + (0.75 * n-1) + (0.5 * n-2) + (0.25 * n-3) 
where n is the value at the current row, n-1 the value at the above row, etc.

corresponding Wikipedia section

上有关加权移动平均线的更多信息

像这样计算移动平均线后我卡住了:

代码示例 1:到目前为止的查询

SELECT
    *,
    AVG (value) OVER (
        ORDER BY
            id
        ROWS BETWEEN
            3 PRECEDING AND CURRENT ROW
FROM
    table

Table 1:

id    value    weighted_moving_average   code_sample_1
...
11     0        0                        0
12     1        1                        0.25
13     0        0.75                     0.25
14     0        0.5                      0.25
15     0        0.25                     0.25
16     0        0                        0
...

这并不花哨,但它是一个开始。

SELECT
    *,
    (SUM (value*0.25) OVER (ORDER BY id ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) +
     SUM (value*0.25) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) +
     SUM (value*0.25) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) +
     value * 0.25) /
    COUNT (value) OVER (ORDER BY id ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
FROM
    table;

如果您希望 window 大小可以轻松更改,那么实现方式将大不相同。

(请注意,我是在 because I am not aware of any website I can test SQL 中开发的。您可能需要调整一些语法。)

Declare @thisManyRows int = 3;
With rowNumber_cte As (
    Select 
        id, 
        [Value],
        RowNo = Row_Number() Over (Order By id)
      From Table1),
windows_cte As (
    Select
        b_id = b.id,
        j_id = j.id,
        j.[Value],
        RowNo2 = @thisManyRows + 1 - Row_Number() Over (Partition By b.id Order By j.id desc),
        n = Count(j.[Value]) Over (Partition By b.id)
      From rowNumber_cte As b
      Join rowNumber_cte As j On j.RowNo Between b.RowNo - @thisManyRows + 1 And b.RowNo)
Select
    id = b_id,
    [Value] = Sum(Case When b_id = j_id Then [Value] Else Null End),
    WeightedAverage = Sum([Value] * 1.0 * (RowNo2 *1.0 / @thisManyRows)) / Min(n)
  From windows_cte
  Group By b_id;

我将解释它的作用,因为它有点神秘:

  1. 将变量设置为移动平均值要考虑的行数(包括当前行)。
  2. rowNumber_cte 中我们分配了一个行号,我们这样做是因为我们不假设 id 将是连续的。
  3. windows_cte 中,我们将 rowNumber_cte 自身连接起来,这样每一行都连接到构成它的所有行 window 计算(参考 @thisManyRows 变量。此 cte 还引入了一个新的 RowNo2 字段,该字段基本上最终将成为分数的分子,该行的值对加权移动平均值的贡献(即当前行,如果 window 是 4 将具有 RowNo2 = 4 并且将具有 4/4 权重)。
  4. windows_cte 还计算 window 中的行数,以更好地处理数据开头没有完整 window.[=35= 的行]
  5. 最后的 select 分组 id,将 window 中每一行的 [Value] 乘以它的权重,然后除以 window 中的行数window: n.