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

如何在SQL中优雅实现多滚动窗口聚合后的Union操作

更简洁的滚动窗口求和方案

针对你这种固定长度的滚动窗口求和需求,完全不用写一堆UNION ALL,有两种更高效简洁的方式:

方法1:先生成窗口范围,再关联计算

先找出所有有效的窗口起始周(这里窗口长度是3周,所以起始周从1到最大周数-2),再和原表关联筛选对应范围的记录,最后聚合求和:

-- 先生成窗口的起始和结束周
WITH window_ranges AS (
    SELECT 
        week AS start_week,
        week + 2 AS end_week
    FROM sale
    GROUP BY week
    HAVING week + 2 <= (SELECT MAX(week) FROM sale)
)
SELECT 
    CONCAT(start_week, '-', end_week) AS period,
    SUM(s.sales) AS total_sales
FROM window_ranges wr
JOIN sale s ON s.week BETWEEN wr.start_week AND wr.end_week
GROUP BY wr.start_week, wr.end_week
ORDER BY wr.start_week;

这个方法的好处是不管窗口数量有多少,都只需要调整week + 2里的数字(对应窗口长度-1),就能自动生成所有有效窗口,不用手动写每个UNION分支。

方法2:先聚合每周销售额,再用滑动窗口函数

如果你的SQL支持窗口函数(比如MySQL 8.0+、PostgreSQL、SQL Server等),可以先按周聚合出每周的总销售额,再用滑动窗口求和:

-- 先计算每周的总销售额
WITH weekly_sales AS (
    SELECT 
        week,
        SUM(sales) AS weekly_total
    FROM sale
    GROUP BY week
)
SELECT 
    CONCAT(week, '-', week + 2) AS period,
    SUM(weekly_total) OVER(
        ORDER BY week 
        ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING
    ) AS total_sales
FROM weekly_sales
WHERE week + 2 <= (SELECT MAX(week) FROM weekly_sales)
ORDER BY week;

这种方式效率更高,因为先做了一次周聚合,减少了后续窗口计算的数据量。窗口函数里的2 FOLLOWING对应窗口长度为3(当前行+后面2行),调整这个数字就能适配不同的窗口长度。

对比你原来的写法,这两种方法都能避免重复编写大量重复的SELECT语句,当窗口数量变多的时候优势特别明显,也不会像笛卡尔积那样生成多余的行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:47:36