滑动窗口移动平均值
使用 BETWEEN PRECEDING AND CURRENT ROW 计算 N 期滚动平均值
滑动窗口移动平均值 是 CoddyKit 上的免费 Coding Interview Prep 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Coding Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Coding Interview Prep 课程共包含 4 节课。
移动平均问题
分析师经常会被问到这个问题:“计算 7 天移动平均收入。”移动平均值(或滚动平均值)通过将每个数据点与其临近数据点求平均,来平滑每日数据中的噪声。
达到面试要求的回答是使用带明确滑动窗口框架的窗口函数 AVG。关键技能在于选择正确的框架边界,使窗口能够沿排序方向正确滑动。
核心模式
移动平均值的形式是 AVG(value) OVER (ORDER BY ... ROWS BETWEEN n PRECEDING AND CURRENT ROW)。窗口会滑动:在每一行上,它包含当前行以及前面的 n 行。
对于每日一行的 7 天窗口,需要向前取 6 行,再加上当前行,总共得到 7 行。这里的差一错误是面试官最常发现的错误。
SELECT
sale_date,
amount,
AVG(amount) OVER (
ORDER BY sale_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS moving_avg_7d
FROM daily_sales;正确计算窗口大小
窗口大小等于前置行数 + 1(+1 代表当前行)。因此:
- 3 行窗口:
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW - 7 行窗口:
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW - 30 行窗口:
ROWS BETWEEN 29 PRECEDING AND CURRENT ROW
在面试中把这个算式说出来,让面试小组看出您是在有意识地计算,而不是猜测。
居中窗口与后向窗口
上面的例子是后向平均值:它只查看过去,因此具有因果性,可以安全地用于预测仪表板。
居中平均值会同时查看前后数据,例如使用 ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING 构成 7 行的居中窗口。居中窗口的平滑效果更加对称,但在实时场景中无法计算最新的几行。请说明具体使用场景需要哪一种窗口。
SELECT
sale_date,
AVG(amount) OVER (
ORDER BY sale_date
ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING
) AS centered_avg_7
FROM daily_sales;窗口边界效应
在数据开头,完整窗口还不存在。对于 7 天后向平均值的第 1 行,只有 1 行可用,因此 AVG 只会对这一个值求平均。
这意味着开头的行会显示基于较少行数的“预热”平均值。面试官会询问如何处理这种情况。有两种选择:接受部分窗口,或者要求完整的行数以隐藏开头的行。
隐藏部分窗口
如果业务要求在完整窗口可用之前显示 NULL,可以在相同框架上使用 COUNT(*),再通过 CASE 表达式将较短的窗口置为 NULL。
这是一个体现严谨性的细节,说明您考虑到了边界处的正确性,而许多候选人会忽略这一点。
SELECT
sale_date,
CASE WHEN COUNT(*) OVER w = 7
THEN AVG(amount) OVER w
END AS moving_avg_7d
FROM daily_sales
WINDOW w AS (
ORDER BY sale_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
);使用 WINDOW 重用框架
前一个查询使用了命名的 WINDOW 子句。当同一个框架需要出现多次时,可以将它定义一次为 WINDOW w AS (...),再通过 OVER w 引用,从而让查询保持 DRY 且易读。
PostgreSQL、MySQL 8 和 SQL 服务器支持命名窗口。在面试中使用命名窗口,可以体现您对窗口函数的熟练程度,而不只是机械复制粘贴。
SELECT
sale_date,
AVG(amount) OVER w AS avg_7d,
SUM(amount) OVER w AS sum_7d
FROM daily_sales
WINDOW w AS (
ORDER BY sale_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
);日历日与行的陷阱
一个容易忽略的陷阱是:如果表中缺少日期,ROWS 6 PRECEDING 覆盖的是最近 7 个已记录的行,实际可能跨越超过 7 个日历日。
如果要计算真正按日历计算且尊重间隔的 7 日平均值,请使用带区间偏移量的 RANGE,或者先连接到完整的日期序列,确保每天都有一行。明确这一点,正是上一课中 ROWS 与 RANGE 的核心理解。
SELECT
sale_date,
AVG(amount) OVER (
ORDER BY sale_date
RANGE BETWEEN INTERVAL '6 days' PRECEDING AND CURRENT ROW
) AS calendar_avg_7d
FROM daily_sales;按组计算移动平均值
与累计总计一样,移动平均值通常需要按实体重置。添加 PARTITION BY,让每个产品或商店拥有自己的滚动窗口,避免数据跨组混合。
框架和排序会在每个分区内部独立运行,因此每个组开头的行都能正确开始自己的预热阶段。
SELECT
product_id,
sale_date,
AVG(amount) OVER (
PARTITION BY product_id
ORDER BY sale_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS product_ma_7d
FROM daily_sales;平滑效果
为什么要这样做?每日收入波动剧烈,而移动平均值可以揭示趋势。分析师常见的做法是同时显示原始值及其平滑曲线,让仪表板同时呈现信号和噪声。
您还可以比较短期和长期移动平均值(例如 7 天与 30 天),从而检测趋势动量,这相当于 SQL 中的移动平均线交叉。
SELECT
sale_date,
amount,
AVG(amount) OVER (ORDER BY sale_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma_7,
AVG(amount) OVER (ORDER BY sale_date
ROWS BETWEEN 29 PRECEDING AND CURRENT ROW) AS ma_30
FROM daily_sales;面试检查清单
要完整回答移动平均问题,请涵盖以下内容:
AVG OVER (ORDER BY ... ROWS BETWEEN n-1 PRECEDING AND CURRENT ROW)。- 窗口大小 = 前置行数 + 1。
- 后向窗口与居中窗口的选择。
- 部分窗口的预热阶段,以及如何隐藏它。
- 缺少日期时的
ROWS与RANGE。 - 使用
PARTITION BY按实体重置。
快速检查
请选择针对每日一行数据的 7 天后向移动平均窗口框架。
总结:移动平均值
移动平均值的形式是 AVG(value) OVER (ORDER BY ... ROWS BETWEEN n-1 PRECEDING AND CURRENT ROW),其中窗口大小等于前置行数加一。请根据使用场景选择后向窗口或居中窗口,使用 COUNT 检查来处理预热行,并在日历间隔很重要时切换到 RANGE 区间。
使用 PARTITION BY 按实体重置,并使用命名的 WINDOW 重用框架。接下来,我们将把累计总计转换为百分比,计算累计占总计的份额。
常见问题解答
「滑动窗口移动平均值」课时是免费的吗?
是的 — 「滑动窗口移动平均值」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Coding Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 Coding Interview Prep 课程共包含 4 节课。
「滑动窗口移动平均值」这节课中我会学到什么?
使用 BETWEEN PRECEDING AND CURRENT ROW 计算 N 期滚动平均值 你通过在浏览器中直接运行的动手代码来练习 Coding Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Coding Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Coding Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「滑动窗口移动平均值」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Coding Interview Prep 课中编写并运行代码吗?
能。每节 Coding Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。