首页 > 解决方案 > TSQL:计算离散时间序列的线性加权(移动)平均值

问题描述

我有一个离散的时间序列,如下所示:

product_id  date    sales_per_day
VSG19   2018-05-19  1.00000000000000
VSG19   2018-05-23  1.00000000000000
VSG19   2018-05-24  2.00000000000000
VSG19   2018-06-25  1.00000000000000
VSG19   2018-07-26  1.00000000000000
VSG19   2018-07-28  1.00000000000000
VSG19   2018-08-01  1.00000000000000
VSG19   2018-08-11  1.00000000000000
VSG19   2018-08-29  1.00000000000000
VSG19   2018-09-11  1.00000000000000
VSG19   2018-09-29  1.00000000000000
VSG19   2018-10-16  1.00000000000000
VSG19   2018-10-25  1.00000000000000
VSG19   2018-11-02  1.00000000000000

我想为此计算线性加权平均值,但我的数据不包含未发生销售的日期。

我已经通过加入日历表解决了这个问题,但我不喜欢这个解决方案。你知道解决这个问题的优雅方法吗?

提前致谢!

PS - 这是 LWMA 的公式:https ://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average

标签: sql-servertsqlsql-server-2017

解决方案


我对那个特定的计算并不太熟悉,但从我刚刚读到的内容来看,你应该能够使用“窗口框架”来计算“滚动信息需要将权重分配给过去的销售。没有看到你的实际公式申请,我不能确定天气是否会起作用。

以下只是我脑海中的一个例子......

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    product_id CHAR(5) NOT NULL,
    [date] DATE NOT NULL,
    sales_per_day DECIMAL(19,14) NOT NULL 
    );
INSERT #TestData (product_id, date, sales_per_day) VALUES
    ('VSG19', '2018-05-19', 1.00000000000000),
    ('VSG19', '2018-05-23', 1.00000000000000),
    ('VSG19', '2018-05-24', 2.00000000000000),
    ('VSG19', '2018-06-25', 1.00000000000000),
    ('VSG19', '2018-07-26', 1.00000000000000),
    ('VSG19', '2018-07-28', 1.00000000000000),
    ('VSG19', '2018-08-01', 1.00000000000000),
    ('VSG19', '2018-08-11', 1.00000000000000),
    ('VSG19', '2018-08-29', 1.00000000000000),
    ('VSG19', '2018-09-11', 1.00000000000000),
    ('VSG19', '2018-09-29', 1.00000000000000),
    ('VSG19', '2018-10-16', 1.00000000000000),
    ('VSG19', '2018-10-25', 1.00000000000000),
    ('VSG19', '2018-11-02', 1.00000000000000);

--===============================================================

SELECT 
    *,
    days_since_last_sale = ISNULL(DATEDIFF(DAY, MAX(td.date) OVER (ORDER BY td.date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), td.date), 0),
    days_from_first_sale = ISNULL(DATEDIFF(DAY, MIN(td.date) OVER (ORDER BY td.date), td.date), 0)
FROM
    #TestData td;

推荐阅读