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

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:分区开头/结尾。

关键字含义示例
UNBOUNDED PRECEDING从最开头行开始整组累加直到当前行
n PRECEDING当前行向前数第 n 行过去 n 行
CURRENT ROW当前行本身仅此行 or 截止此行
n FOLLOWING当前行之后第 n 行未来 n 行
UNBOUNDED 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

相关文章:

SQL: 窗口滑动(Sliding Window)

目录 什么是“窗口”&#xff1f; 什么是“滑动”&#xff1f; &#x1f50d; 滑动窗口的核心&#xff1a; &#x1f552; 什么是时间窗口&#xff1f;&#xff08;Time Window&#xff09; 时间窗口的基本结构 时间窗口的三种常见形式 &#x1f4ca; 什么是行窗口&…...

学习日记-day20-6.1

完成目标&#xff1a; 知识点&#xff1a; 1.集合_Collections集合工具类 方法:static <T> boolean addAll(Collection<? super T> c, T... elements)->批量添加元素 static void shuffle(List<?> list) ->将集合中的元素顺序打乱static <T>…...

【音视频】 FFmpeg 解码H265

一、概述 实现了使用FFmpeg读取对应H265文件&#xff0c;并且保存为对应的yuv文件 二、实现流程 读取文件 将H265/H264文件放在build路径下&#xff0c;然后指定输出为yuv格式 在main函数中读取外部参数 if (argc < 2){fprintf(stderr, "Usage: %s <input file&…...

Linux 系统 Docker Compose 安装

个人博客地址&#xff1a;Linux 系统 Docker Compose 安装 | 一张假钞的真实世界 本文方法是直接下载 GitHub 项目的 release 版本。项目地址&#xff1a;GitHub - docker/compose: Define and run multi-container applications with Docker。 执行以下命令将发布程序加载至…...

软件测试|FIT故障注入测试工具——ISO 26262合规下的智能汽车安全验证引擎

FIT&#xff08;Fault Injection Tester&#xff09;是SURESOFT专为汽车电子与工业控制设计的自动化故障注入测试工具​&#xff0c;基于ISO 26262等国际安全标准开发&#xff0c;旨在解决传统测试中效率低、成本高、安全隐患难以复现的问题&#xff0c;其核心功能包括&#xf…...

3D拟合测量水杯半径

1&#xff0c;目的。 测量水杯的半径 如图所示&#xff1a; 2&#xff0c;原理。 对 3D 点云对象 进行圆柱体拟合&#xff0c;获取拟合后的半径。 3&#xff0c;注意事项。 在Halcon中使用fit_primitives_object_model_3d进行圆柱体拟合时&#xff0c;输出的primitive_para…...

(21)量子计算对密码学的影响

文章目录 2️⃣1️⃣ 量子计算对密码学的影响 &#x1f30c;&#x1f50d; TL;DR&#x1f680; 量子计算&#xff1a;密码学的终结者&#xff1f;⚡ 量子计算的破坏力 &#x1f510; Java密码学体系面临的量子威胁&#x1f525; 受影响最严重的Java安全组件 &#x1f6e1;️ 后…...

Python训练打卡Day38

Dataset和Dataloader类 知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 在遇到大规模数据集时&#xff0c;显存常常无法一次性存储所有数据&#xff0c;所以需要使用分批训练的…...

Selenium基础操作方法详解

Selenium基础操作方法详解&#xff1a;从零开始编写自动化脚本&#xff08;附完整代码&#xff09; 引言 Selenium是自动化测试和网页操作的利器&#xff0c;但对于新手来说&#xff0c;掌握基础操作是成功的第一步。本文将手把手教你使用Selenium完成浏览器初始化、元素定位、…...

Kali Linux从入门到实战:系统详解与工具指南

一、Kali Linux简介 Kali Linux是一款基于Debian的Linux发行版&#xff0c;专为渗透测试和网络安全审计设计&#xff0c;由Offensive Security团队维护。其前身是BackTrack&#xff0c;目前集成了超过600款安全工具&#xff0c;覆盖渗透测试全流程&#xff0c;是网络安全领域…...

【大模型】Bert变种

1. RoBERTa&#xff08;Robustly optimized BERT approach&#xff09; 核心改动 取消 NSP&#xff08;Next Sentence Prediction&#xff09;任务&#xff0c;研究发现 NSP 对多数下游任务贡献有限。动态遮蔽&#xff08;dynamic masking&#xff09;&#xff1a;每个 epoch …...

vue-09(使用自定义事件和作用域插槽构建可重用组件)

实践练习&#xff1a;使用自定义事件和作用域插槽构建可重用组件 构建可重用的组件是高效 Vue.js 开发的基石。本课重点介绍如何通过自定义事件和范围插槽来增强组件的可重用性&#xff0c;从而实现更灵活和动态的组件交互。我们将探索如何定义和发出自定义事件&#xff0c;使…...

简单三步FastAdmin 开源框架的安装

简单三步FastAdmin 开源框架的安装 第一步&#xff1a;新建站点1&#xff0c;在宝塔面板中&#xff0c;创建一个新的站点&#xff0c;并填写项目域名。 第二步&#xff1a;上传框架1&#xff0c;框架下载2&#xff0c;上传解压缩 第三步&#xff1a;配置并安装1&#xff0c;进入…...

RISC-V 开发板 MUSE Pi Pro 搭建 Spacengine AI模型部署环境

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro 搭建 Spacengine AI模型部署环境 Spacengine 是由 进迭时空 研发的一套 AI 算法模型部署工具&#xff0c;可以方便的帮助用户部署自己的模型在端侧&#xff0c; 环境部署的方式&#xff0c;官方提供了两种方式&#xff1a; do…...

C++面试5——对象存储区域详解

C++对象存储区域详解 核心观点:内存是程序员的战场,存储区域决定对象的生杀大权!栈对象自动赴死,堆对象生死由你,全局对象永生不死,常量区对象只读不灭。 一、四大地域生死簿 栈区(Stack) • 特点:自动分配释放,速度极快(类似高铁进出站) • 生存期:函数大括号{}就…...

【Unity】AudioSource超过MaxDistance还是能听见

unity版本&#xff1a;2022.3.51f1c1 将SpatialBlend拉到1即可 或者这里改到0 Hearing audio outside max distance - #11 by wderstine - Questions & Answers - Unity Discussions...

基于 51 单片机的智能饮水机控制系统设计与实现

一、引言 随着物联网技术的发展,传统家电的智能化升级成为趋势。本文提出一种基于 51 单片机的智能饮水机设计方案,实现水温精准控制、水位监测、人机交互等功能,具有成本低、稳定性高的特点,适用于家庭和小型办公场景。 二、硬件设计 2.1 核心芯片选型 单片机:选用STC…...

Qt 读取和写入 INI 格式的配置文件

Qt 读取和写入 INI 格式的配置文件 前言&#xff1a;INI 配置文件在 Qt 开发中的重要性基础夯实&#xff1a;INI 文件结构与 QSettings 核心概念1. INI 文件的基本结构2. QSettings 类概述3. 初始化 QSettings 对象4. 基本读写操作5. 高级操作技巧5.1 处理数组和列表5.2 检查键…...

互联网大厂Java求职面试:AI与云原生架构实战解析

互联网大厂Java求职面试&#xff1a;AI与云原生架构实战解析 面试背景设定 场景&#xff1a;某互联网头部企业技术总监办公室&#xff0c;窗外是城市夜景&#xff0c;室内灯光柔和。面试官是一位经验丰富的技术总监&#xff0c;面前摆着一杯黑咖啡和候选人的简历。 候选人&a…...

Spring:从青铜到王者,你的Java修炼手册

一、Spring家族宇宙&#xff1a;原来你是这样的框架&#xff08;青铜段位&#xff09; 1.1 Spring的"前世今生"&#xff1a;从泡面到满汉全席 ​​2002年的泡面哲学​​&#xff1a;Rod Johnson在厨房煮泡面时突然顿悟&#xff1a;"Java开发为什么不能像泡面一…...

React和原生事件的区别

一、核心差异对比表 维度原生事件React 事件绑定语法HTML 属性&#xff08;onclick&#xff09;或 DOM API&#xff08;addEventListener&#xff09;JSX 中使用驼峰式属性&#xff08;onClick&#xff09;绑定位置直接绑定到具体 DOM 元素统一委托到根节点&#xff08;React …...

Qt creator 设计页面控件认识与了解

记录一下 Qt 中的认识与了解&#xff1a; 在 Qt 中&#xff0c;这些功能属于 Qt Designer 的组件过滤系统&#xff0c;旨在帮助开发者在对象浏览器中快速定位和使用不同类型的控件和组件。以下是每个功能的详细讲解&#xff1a; ‌Layouts&#xff08;布局&#xff09;‌&…...

命象架构法 02|你的系统有“用神”吗?

命理中说:“八字无用神,是虚命。” 系统架构中说:“模块无主线,是垃圾桶。” 你设计了无数类,却不知道哪个是核心。 那么你的系统,很可能是没有“用神”的。 01|什么是“用神”?不是你以为的“最好” 命理中,“用神”不是“最强的”,而是对命主最有帮助的。 比如一…...

NVIDIA Mellanox BlueField-2 DPU(Data Processing Unit)智能网卡的调试和使用

专有名词 OOB&#xff1a; BMC&#xff1a; BFB&#xff1a; EMMC&#xff1a; 关键词解释eMMCEmbedded Multi-Media Card——把 NAND 闪存颗粒与控制器封装在一起的板载存储件&#xff0c;类似手机里的“内置储存” .deb&#xff1a;文件是​​Debian软件包格式​​的专…...

Tomcat- AJP协议文件读取/命令执行漏洞(幽灵猫复现)详细步骤

一、漏洞描述 Apache Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器.默认情况下,Apache Tomcat会开启AJP连接器,方便与其他Web服务器通过AJP协议进行交互.但Apache Tomcat在AJP协议的实现上存在漏洞,导致攻击者可以通过发送恶意的AJP请求,可以读取或者包含Web应…...

B1、进度汇报(— 25/05/31)

本文档汇总了各成员在 2025 年 5 月 11 日 ~ 5 月 31 日完成的工作。我们遇到了进度问题&#xff08;收工后需反思&#xff09;&#xff1a; 本学期第十四周&#xff08;05/19 ~ 05/25&#xff09;有相当多课程需要提交实验结果或上台展示。本学期第十六周&#xff08;06/02 ~…...

工作流引擎-11-开源 BPM 项目 jbpm

工作流引擎系列 工作流引擎-00-流程引擎概览 工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎&#xff0c;支持现实世界的流程自动化需求 工作流引擎-02-BPM OA ERP 区别和联系 工作流引擎-03-聊一聊流程引擎 工作流引擎-04-流程引擎 activiti 优…...

【Prompt Engineering】摸索出的一些小套路

prompt 优化方法 &#x1f539; 1. 通用结构模板 模块化的Prompt&#xff1a;Prompt 划分成边界清晰的模块&#xff0c;不同模块间都应有明确的分隔符 以下是通用 Prompt 的推荐结构&#xff1a; [角色设定] [任务描述] [输出格式要求] [补充上下文]角色设定&#xff1a;…...

CSS强制div单行显示不换行

在CSS中&#xff0c;要让<div>的内容强制单行显示且不换行&#xff0c;可通过以下属性组合实现&#xff1a; 核心解决方案&#xff1a; css 复制 下载 div {white-space: nowrap; /* 禁止文本换行 */overflow: hidden; /* 隐藏溢出内容 */text-overflow: e…...

js的时间循环的讲解

JavaScript 事件循环(Event Loop)是其运行时的核心机制,负责处理异步操作,确保单线程的 JavaScript 能够高效地处理并发任务。下面从多个角度详细解析事件循环机制: 1. 核心概念 (1)执行栈(Call Stack) 定义:JavaScript 是单线程的,所有同步任务都在执行栈中依次执…...