SQL 中分区的加权移动平均线

Weighted moving average with partitions in SQL

我有一个简单的 table,其中包含按日期 (YYYYMMDD) 销售的不同产品。天数多,品多。 table 看起来像这样:

date      product     sales
...
20210101  Apples       112
20210101  Bananas      13
20210102  Apples       12
20210102  Bananas      101
20210103  Apples       18
20210103  Bananas      155
20210101  Lemons       14
... 

我需要计算每个产品的 3 天加权移动平均值。主要棘手的事情是分区。我试图在这段代码中压缩它:

    SELECT table.date,
       max(table.sales) as sales,
       CASE 
       WHEN table.date - (select min(date) from table) >1
       THEN sum(weighting * ma_table.sales)
       END as WMA 
FROM table
JOIN table AS ma_table ON table.date - ma_table.date BETWEEN 0 AND 2
JOIN (SELECT id_1, 1/(2 + 1.) as weighting FROM (VALUES (0, 1, 2)) as t(id_1)) weights ON
  id_1 = table.date - ma_table.date
GROUP BY table.date
ORDER BY table.date

是否可以使用此代码完成任何操作以在其中包含分区?

下面是SQL计算每个产品的3天移动平均线, 使用 window 函数。
这是你想要的吗?

with
a as ( -- serial numbers upto N (=3)
    select row_number() over () as i
    from TBL
    limit 3
),
b as (
  select
      TBL.date, TBL.product, TBL.sales,
      lag("sales", cast(a.i - 1 as integer)) 
        over(partition by TBL.product, a.i order by date) as sales2,
      (3 - a.i + 1) as weight
  from TBL
  cross join a
)
select date, product, sales,
    sum(weight*sales2) / (3*(3+1)/2) as avg
from b
group by date, product, sales
order by product, date

DEMO

所以我猜是这样的

create table yourtable (
 id int primary key, 
 "date" date, 
 product varchar(30), 
 sales decimal(18,2)
)

insert into yourtable 
(id, "date" , product, sales) values
  (1, '2021-01-01', 'Apples',  112)
, (2, '2021-01-02', 'Apples',   12)
, (3, '2021-01-03', 'Apples',   18)
, (4, '2021-01-01', 'Bananas',  13)
, (5, '2021-01-02', 'Bananas', 101)
, (6, '2021-01-03', 'Bananas', 155)
, (7, '2021-01-01', 'Lemons',   14)
select "date", product, sales
, cast((prev2+prev1*2+sales*3)/(1+2+3) as decimal(18,2)) as WMA
from (
select "date", product, sales
, lag(sales, 2, 0) over (partition by product order by "date") as prev2
, lag(sales, 1, 0) over (partition by product order by "date") as prev1
from yourtable
) q
order by product, "date"
date       | product |  sales |    wma
:--------- | :------ | -----: | -----:
2021-01-01 | Apples  | 112.00 |  56.00
2021-01-02 | Apples  |  12.00 |  43.33
2021-01-03 | Apples  |  18.00 |  31.67
2021-01-01 | Bananas |  13.00 |   6.50
2021-01-02 | Bananas | 101.00 |  54.83
2021-01-03 | Bananas | 155.00 | 113.33
2021-01-01 | Lemons  |  14.00 |   7.00

db<>fiddle here

无限加权滚动平均值的数字可能如下所示。

select "date", product, sales
, cast(sum(cnt * sales) 
       over (partition by product ROWS BETWEEN UNBOUNDED PRECEDING AND current row)
     / sum(cnt) 
       over (partition by product ROWS BETWEEN UNBOUNDED PRECEDING AND current row
  ) as decimal(18,2)) as UnboundedWeightedMovingAverage
from (
select "date", product, sales
, count(*) over (partition by product order by "date" asc) as cnt
from yourtable
) q
order by product, "date"
date       | product |  sales | unboundedweightedmovingaverage
:--------- | :------ | -----: | -----------------------------:
2021-01-01 | Apples  | 112.00 |                         112.00
2021-01-02 | Apples  |  12.00 |                          45.33
2021-01-03 | Apples  |  18.00 |                          31.67
2021-01-01 | Bananas |  13.00 |                          13.00
2021-01-02 | Bananas | 101.00 |                          71.67
2021-01-03 | Bananas | 155.00 |                         113.33
2021-01-01 | Lemons  |  14.00 |                          14.00

db<>fiddle here