当前位置: 首页 > news >正文

SQL: 窗口滑动(Sliding Window)

目录

什么是“窗口”?

什么是“滑动”?

🔍 滑动窗口的核心: 

 🕒 什么是时间窗口?(Time Window)

时间窗口的基本结构

时间窗口的三种常见形式 

📊 什么是行窗口?(Row-Based Window) 

行窗口的结构

常见用途与写法

ROWS vs RANGE


什么是“窗口”?

在数据分析中,“窗口”是一个“范围”或“区间”的意思。比如你每天记录一次体重,今天是 2024-06-01,那么:

  • 如果你说“最近 3 天的平均体重”,那这个“最近 3 天”就是一个窗口。

  • 它包含了:2024-05-30、2024-05-31、2024-06-01

什么是“滑动”?

滑动(sliding),就是:这个时间范围是不断往前“滑动”的,不是固定不变的。

举个例子,现在有如下每天的体重记录:

日期体重(kg)
6月1日60
6月2日61
6月3日62
6月4日63
6月5日64

你要计算「每一天的过去 3 天平均体重」:

第一步:6月3日的窗口 = 6月1日 ~ 6月3日

  • 数据:60 + 61 + 62

  • 平均:61

第二步:6月4日的窗口 = 6月2日 ~ 6月4日

  • 数据:61 + 62 + 63

  • 平均:62

第三步:6月5日的窗口 = 6月3日 ~ 6月5日

  • 数据:62 + 63 + 64

  • 平均:63

当前日期窗口起始窗口结束平均体重
6月3日6月1日6月3日61
6月4日6月2日6月4日62
6月5日6月3日6月5日63

 用一个大小为 3 天的窗口,在时间线上每天滑动一步,每次都计算窗口内的总和或平均值。

🔍 滑动窗口的核心: 

窗口滑动 = 一种时间上的移动聚合

固定窗口大小,每次时间前进一天,就“滑动”一次。

你可以想象:一个“透明的框”,只能装 3 天数据,这个框不断往右移动,每次移动就重新统计框里的数据。


 窗口滑动可以分为以下两大类

窗口类型滑动单位常见关键词举例说明
 时间窗口时间(天、小时)date, interval最近 7 天平均销售额
 行窗口行数(记录数)ROWS BETWEEN当前行及前 6 行的平均销售额

 🕒 什么是时间窗口?(Time Window)

时间窗口是一种以“时间”为单位的滑动分析方法。

比如说:

我想知道每一天的“过去 7 天”销售额总和或平均值。

举例:

  • 今天是 2025-06-01

  • 时间窗口就是:2025-05-26 到 2025-06-01

  • 明天到了 2025-06-02,窗口就变成:2025-05-27 到 2025-06-02

这就是一个“固定宽度、滑动前进”的时间分析窗口。

时间窗口的基本结构

<窗口函数> OVER ([PARTITION BY 列名1, 列名2, ...]ORDER BY 时间列 [ASC|DESC]RANGE BETWEEN 间隔 PRECEDING AND 间隔 FOLLOWING
)

RANGE BETWEEN:基于 ORDER BY 列的值范围(而非行数),常见选项:

  • INTERVAL 'n' DAY/HOUR/SECOND PRECEDING:向前 n 个时间单位。

  • CURRENT ROW:当前行时间点。

  • INTERVAL 'n' DAY/HOUR/SECOND FOLLOWING:向后 n 个时间单位。

  • UNBOUNDED PRECEDING/FOLLOWING:分区开头/结尾。

示例:

SELECTorder_date,revenue,SUM(revenue) OVER (PARTITION BY customer_idORDER BY order_dateRANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW) AS last_7_days_revenue
FROM orders;


时间窗口的实现方式

在 SQL 中,时间窗口不直接写成 RANGE BETWEEN,一般通过如下方式实现:

✅ 方法一:子查询 + BETWEEN 做“滑动聚合”

SELECTA.visited_on,(SELECT SUM(B.amount)FROM Customer BWHERE B.visited_on BETWEEN A.visited_on - INTERVAL 6 DAY AND A.visited_on) AS sum_amount
FROM Customer A

每一行 A 都会向前回顾 7 天内的数据 B,进行统计。

  • 外层查询:遍历 Customer 表(别名 A),获取每行的 visited_on。

  • 子查询:针对每行 A.visited_on,从 Customer 表(别名 B)筛选 visited_on 在前6天(含当天)范围内的记录,计算 amount 的总和。

  • BETWEEN:定义时间窗口,从 A.visited_on - INTERVAL '6' DAY 到 A.visited_on。

✅ 方法二:自连接(JOIN)+ 时间范围 

SELECTA.visited_on,SUM(B.amount) AS amount
FROM Customer A
JOIN Customer BON B.visited_on BETWEEN A.visited_on - INTERVAL 6 DAY AND A.visited_on
GROUP BY A.visited_on

 让每一行 A 和前 6 天的 B 匹配,形成一个窗口,然后聚合。

  • 自连接:主表 Customer(别名 A)与自身(别名 B)连接,ON 条件限定 B.visited_on 在 A.visited_on 前6天(含当天)的范围内。

  • 时间范围:用 BETWEEN 指定从 A.visited_on - INTERVAL '6' DAY 到 A.visited_on。

  • GROUP BY:按 A.visited_on 分组,计算 B.amount 的总和。

时间窗口的三种常见形式 

① 滑动窗口(Sliding Window)——「有重叠」

  • 窗口大小固定(比如 7 天)

  • 每天都往前滑动一步

  • 常用于计算“过去 7 天的平均值”之类的场景

🧠 比如:

当前日期窗口范围含义
6月7日6月1日~6月7日计算这 7 天总消费
6月8日6月2日~6月8日继续往前滑一格

② 滚动窗口(Tumbling Window)——「无重叠」

  • 窗口之间完全不重叠

  • 一段时间为一个完整窗口,下一段重新开始

🧠 比如:

窗口编号窗口时间范围
W16月1日 00:00 ~ 6月1日 05:00
W26月1日 05:00 ~ 6月1日 10:00
W36月1日 10:00 ~ 6月1日 15:00

常用于按小时、每天、每 5 分钟等做不重叠汇总统计。

SELECTDATE_TRUNC('day', visited_on) AS window_start,SUM(amount) AS tumbling_sum
FROM Customer
GROUP BY DATE_TRUNC('day', visited_on);
  • DATE_TRUNC:将 visited_on 截断到指定时间单位(如 'day'、'week'),划分非重叠窗口。

  • GROUP BY:按截断后的时间分组,计算每段的聚合(如 SUM)。

  • 替代实现(固定时间间隔):

SELECTFLOOR(DATEDIFF('day', '2020-01-01', visited_on) / 7) AS window_id,SUM(amount) AS tumbling_sum
FROM Customer
GROUP BY FLOOR(DATEDIFF('day', '2020-01-01', visited_on) / 7);

 使用 DATEDIFF 计算天数并划分固定7天窗口

③ 会话窗口(Session Window)——「不固定长度」

  • 用户一段时间内连续操作归为一组

  • 中间空闲超过某阈值就开启新窗口

 🧠 比如:用户 A 从 9:00 ~ 9:20 连续浏览页面,中间没有断开,属于一个“会话窗口”;
如果他 9:40 又回来访问,就开启另一个窗口。

这种常用于用户行为分析,比如“每次访问网站的行为路径”。 

SELECTvisited_on,SUM(amount) OVER (PARTITION BY session_id) AS session_sum
FROM (SELECTvisited_on,amount,SUM(CASE WHEN DATEDIFF('hour', prev_visited_on, visited_on) > 1 THEN 1 ELSE 0 END) OVER (ORDER BY visited_on) AS session_idFROM (SELECTvisited_on,amount,LAG(visited_on) OVER (ORDER BY visited_on) AS prev_visited_onFROM Customer) t
) t2;
  • LAG:获取前一行 visited_on,计算与当前行的时间差。

  • CASE WHEN:若时间差超过阈值(如1小时),标记新会话。

  • SUM OVER:累计会话标记生成 session_id,按 session_id 分组计算聚合。

  • PARTITION BY session_id:按会话分组聚合。


📊 什么是行窗口?(Row-Based Window) 

行窗口(Row Window)是以“数据行的数量”为基础定义的一个分析范围,而不是时间。

🧠 举个直觉例子:

假设你有一个按时间排序的销售数据表,你想计算“当前行以及前两行”的平均销售额。

这时不管这几行是哪几天的数据,只要是“当前行之前的 2 行 + 当前行”,就会参与计算。

 这种滑动就是**“按行”滑动,而不是按时间段”滑动**,所以叫行窗口(Row Window)。

行窗口的结构

在 SQL 中,行窗口常使用 窗口函数(Window Function)+ OVER 子句 实现。

常见语法:

<窗口函数> OVER ([PARTITION BY 列名1, 列名2, ...]ORDER BY 列名 [ASC|DESC]ROWS BETWEEN 起始点 AND 结束点
)SELECTemployee_id,salary,SUM(salary) OVER (PARTITION BY department_idORDER BY salaryROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS moving_sum
FROM employees;

计算每个部门内,按薪资排序的当前行、前一行、后一行的薪资总和。 

  • 窗口函数:如 SUM()、AVG()、ROW_NUMBER()、RANK() 等。

  • PARTITION BY:可选,按指定列分组,类似 GROUP BY,但保留原始行。

  • ORDER BY:定义窗口内行的排序方式,影响累积计算。

  • ROWS BETWEEN:定义窗口范围,常见选项:

    • UNBOUNDED PRECEDING:从分区开头。

    • n PRECEDING:前 n 行。

    • CURRENT ROW:当前行。

    • n FOLLOWING:后 n 行。

    • UNBOUNDED FOLLOWING:到分区结尾。

常见用途与写法

✅ ① 计算“前 N 行”的累计或平均

SELECTvisited_on,amount,AVG(amount) OVER (ORDER BY visited_onROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS avg_3_days
FROM Customer;

实现“每行向前看 2 行 + 当前行”的平均销售额。

✅ ② 计算“排名”、“累计和”、“同比增长” 

SUM(amount) OVER (ORDER BY visited_onROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)

 从第一行开始,累计到当前行的总销售额(running total)

ROWS vs RANGE

比较点ROWSRANGE
控制的是行数(位置)时间范围(值的范围)
示例前两行:ROWS BETWEEN 2 PRECEDING前 7 天:RANGE BETWEEN INTERVAL 7 DAY
支持度MySQL 完整支持MySQL 基本不支持 INTERVAL 用于 RANGE

 

相关文章:

  • C++前缀和介绍
  • MyBatisPlus--条件构造器及自定义SQL详解
  • Linux(信号)
  • PostgreSQL的扩展 insert_username
  • 数据库系统概论(十四)详细讲解SQL中空值的处理
  • 连接天际,守护通信—5G航天时代的电流守卫与浪涌盾牌
  • Caliper压力测试
  • vue · 路由传参query和params
  • Codeforces Round 1028 (Div. 2)(A-D)
  • 深入理解 Linux 文件系统与日志文件分析
  • C++ list代码练习、set基础概念、set对象创建、set大小操作
  • 从 AMQP 到 RabbitMQ:核心组件设计与工作原理(二)
  • 阿里云国际站,如何通过代理商邀请的链接注册账号
  • leetcode93.复原IP地址:回溯算法中段控制与前导零处理的深度解析
  • leetcode hot100 二叉树(二)
  • 【黑马程序员uniapp】项目配置、请求函数封装
  • 如何使用DAXStudio将PowerBI与Excel连接
  • 天机学堂-分页查询
  • 从线性方程组角度理解公式 s=n−r(3E−A)
  • 【头歌实验】Keras机器翻译实战
  • 西安发布最新通知公告/seo排名赚app官网
  • 做设计排版除了昵图网还有什么网站/采集站seo提高收录
  • 网站的域名分为哪些/徐州网站设计
  • 网站建设四段合一/seo排名赚app多久了
  • 网站后台怎么修改代码/网站发布与推广方案
  • wordpress隐藏网站/百度一下知道官网