You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL实现滑动14天平均值统计的最优方案咨询

实现14天滚动窗口平均值统计的最优方案

不推荐使用循环实现,SQL是面向集合的查询语言,循环逐行操作的性能远低于集合运算,而且容易出现边界判断错误。以下是适配你需求的两种实现方案,你使用的DATEADD、GETDATE属于SQL Server语法,方案默认适配SQL Server环境:

方案1:CTE递归生成窗口+批量计算(推荐)

这个方案的逻辑和你熟悉的Python列表生成思路类似:先批量生成所有合法的14天不重叠窗口,再一次性关联原表计算所有窗口的平均值,直接写入新表,不需要手动逐次追加数据。

WITH DateBounds AS (
    -- 先获取表中数据的时间边界,避免用GETDATE()生成超出数据范围的空窗口
    SELECT MIN(RecordDate) AS min_date, MAX(RecordDate) AS max_date
    FROM ResultsData
),
WindowSeries AS (
    -- 递归生成所有不重叠的14天窗口,从最新数据日期往前倒推
    SELECT 
        DATEADD(DAY, -14, max_date) AS start_date,
        max_date AS end_date
    FROM DateBounds
    UNION ALL
    SELECT 
        DATEADD(DAY, -14, start_date) AS start_date,
        DATEADD(DAY, -14, end_date) AS end_date
    FROM WindowSeries
    CROSS JOIN DateBounds
    -- 终止条件:窗口起始日期不早于表中最早的数据日期
    WHERE DATEADD(DAY, -14, start_date) >= min_date
)
-- 计算每个窗口的平均值并写入新表NewAvgResult
SELECT 
    AVG(rd.NumberValue) AS average,
    ws.start_date,
    ws.end_date
INTO NewAvgResult
FROM WindowSeries ws
LEFT JOIN ResultsData rd
    ON rd.RecordDate BETWEEN ws.start_date AND ws.end_date
GROUP BY ws.start_date, ws.end_date
ORDER BY ws.end_date DESC

方案优势

  • 性能远高于循环实现,数据量越大优势越明显
  • 自动处理边界,不会出现窗口超出数据范围的问题
  • 一次查询完成所有计算和新表创建,不需要额外的插入操作

方案2:循环实现(仅小数据量场景使用)

如果你的数据库版本不支持CTE递归,可以用循环实现,注意不要用GETDATE()作为窗口基准,用表中实际的最大数据日期避免生成空窗口:

-- 先创建结果存储表
CREATE TABLE NewAvgResult (
    average FLOAT,
    start_date DATE,
    end_date DATE
)
DECLARE @min_date DATE, @current_start DATE, @current_end DATE
-- 初始化时间边界
SELECT 
    @min_date = MIN(RecordDate),
    @current_end = MAX(RecordDate)
FROM ResultsData
SET @current_start = DATEADD(DAY, -14, @current_end)

WHILE @current_start >= @min_date
BEGIN
    -- 插入当前窗口的计算结果
    INSERT INTO NewAvgResult(average, start_date, end_date)
    SELECT 
        AVG(NumberValue) AS average,
        @current_start AS start_date,
        @current_end AS end_date
    FROM ResultsData
    WHERE RecordDate BETWEEN @current_start AND @current_end
    -- 窗口往前移动14天
    SET @current_end = @current_start
    SET @current_start = DATEADD(DAY, -14, @current_end)
END

补充:如果需要逐行滑动的14天平均值

如果你的需求不是14天不重叠窗口,而是每天都生成往前14天的滑动平均值,可以直接用窗口函数实现,逻辑更简单:

SELECT 
    AVG(NumberValue) OVER (ORDER BY RecordDate ROWS BETWEEN 13 PRECEDING AND CURRENT ROW) AS average,
    DATEADD(DAY, -13, RecordDate) AS start_date,
    RecordDate AS end_date
INTO NewSlidingAvgResult
FROM ResultsData
ORDER BY RecordDate DESC

内容的提问来源于stack exchange,提问作者tcasey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:45:06