使用窗口函数

发布时间:2026/11/5 13:26:54

使用窗口函数 在复杂数据分析、报表统计、排名计算等场景中经常使用。窗口函数是 SQL 中非常强大的功能可以在不改变行数的情况下对每一行进行计算同时保留原始数据。下面我从核心概念、语法结构、常用函数分类、实战案例、性能优化几个维度来系统说明。 窗口函数是什么窗口函数是在一个“窗口”记录集合上执行计算但不会将多行合并为一行每行都保留自己的身份同时可以获得聚合结果。对比聚合函数特性普通聚合函数窗口函数行数变化多行 → 一行行数不变典型函数SUM(),AVG(),COUNT()ROW_NUMBER(),RANK(),SUM() OVER()使用场景汇总统计排名、累计、移动平均、环比同比-- ❌ 聚合函数多行合并成一行SELECTdepartment,AVG(salary)FROMemployeesGROUPBYdepartment;-- ✅ 窗口函数每行保留同时显示部门平均工资SELECTname,department,salary,AVG(salary)OVER(PARTITIONBYdepartment)ASdept_avgFROMemployees; 语法结构窗口函数OVER([PARTITIONBY分区字段]-- 可选将数据分组[ORDERBY排序字段]-- 可选定义排序影响排名类函数[ROWS/RANGE 窗口范围]-- 可选定义帧滑动窗口)三种核心组成部分窗口函数PARTITION BY分组ORDER BY排序窗口帧滑动范围计算每个部门内按工资排序取前三行/累计到当前 窗口函数分类1️⃣ 排名类函数函数说明示例结果ROW_NUMBER()连续排名不跳号1,2,3,4RANK()跳跃排名相同值同排名1,2,2,4DENSE_RANK()密集排名相同值同排名连续1,2,2,3NTILE(n)分成 n 组1,1,2,2,3,3SELECTname,department,salary,ROW_NUMBER()OVER(ORDERBYsalaryDESC)ASrow_num,RANK()OVER(ORDERBYsalaryDESC)ASrank_num,DENSE_RANK()OVER(ORDERBYsalaryDESC)ASdense_rank_num,NTILE(4)OVER(ORDERBYsalaryDESC)ASquartileFROMemployees;结果示例name | department | salary | row_num | rank_num | dense_rank_num | quartile -------|------------|--------|---------|----------|----------------|---------- 张三 | 技术部 | 50000 | 1 | 1 | 1 | 1 李四 | 技术部 | 45000 | 2 | 2 | 2 | 1 王五 | 销售部 | 45000 | 3 | 2 | 2 | 2 赵六 | 销售部 | 40000 | 4 | 4 | 3 | 22️⃣ 聚合类窗口函数在窗口上使用聚合函数相当于“移动汇总”或“分组汇总但不合并行”。函数说明SUM() OVER()累计求和AVG() OVER()移动平均COUNT() OVER()累计计数MAX() / MIN() OVER()窗口内最大/最小值-- 累计销售额按日期SELECTorder_date,amount,SUM(amount)OVER(ORDERBYorder_date)AScumulative_amount,AVG(amount)OVER(ORDERBYorder_dateROWSBETWEEN6PRECEDINGANDCURRENTROW)ASma_7dFROMorders;3️⃣ 取值类窗口函数获取窗口内指定位置的值。函数说明LAG(column, n)获取当前行前第 n 行的值LEAD(column, n)获取当前行后第 n 行的值FIRST_VALUE(column)窗口内第一行的值LAST_VALUE(column)窗口内最后一行的值NTH_VALUE(column, n)窗口内第 n 行的值-- 环比增长计算SELECTorder_date,amount,LAG(amount,1)OVER(ORDERBYorder_date)ASprev_day_amount,(amount-LAG(amount,1)OVER(ORDERBYorder_date))/LAG(amount,1)OVER(ORDERBYorder_date)*100ASgrowth_rate_pctFROMdaily_sales; 实战案例案例 1员工工资排名部门内-- 需求查询每个部门工资前 3 名的员工WITHranked_employeesAS(SELECTname,department,salary,DENSE_RANK()OVER(PARTITIONBYdepartmentORDERBYsalaryDESC)ASrank_in_deptFROMemployees)SELECT*FROMranked_employeesWHERErank_in_dept3;案例 2用户购买累计金额时间序列-- 需求计算每个用户的累计消费金额SELECTuser_id,order_date,amount,SUM(amount)OVER(PARTITIONBYuser_idORDERBYorder_dateROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW)AScumulative_amountFROMorders;案例 37 日移动平均平滑曲线-- 需求计算每日销售额的 7 日移动平均SELECTorder_date,daily_amount,AVG(daily_amount)OVER(ORDERBYorder_dateROWSBETWEEN6PRECEDINGANDCURRENTROW)ASma_7daysFROMdaily_sales;案例 4同比环比计算-- 需求计算每月销售额的环比和同比增长WITHmonthly_salesAS(SELECTDATE_FORMAT(order_date,%Y-%m)ASmonth,SUM(amount)AStotal_amountFROMordersGROUPBYDATE_FORMAT(order_date,%Y-%m))SELECTmonth,total_amount,LAG(total_amount,1)OVER(ORDERBYmonth)ASprev_month_amount,(total_amount-LAG(total_amount,1)OVER(ORDERBYmonth))/LAG(total_amount,1)OVER(ORDERBYmonth)*100ASmom_growth,LAG(total_amount,12)OVER(ORDERBYmonth)ASprev_year_amount,(total_amount-LAG(total_amount,12)OVER(ORDERBYmonth))/LAG(total_amount,12)OVER(ORDERBYmonth)*100ASyoy_growthFROMmonthly_sales;案例 5填充空值使用 LAG/LEAD-- 需求将 NULL 值填充为前一个非 NULL 值SELECTdate,original_value,COALESCE(original_value,LAG(original_value)OVER(ORDERBYdate))ASfilled_valueFROMincomplete_data; 窗口帧Frame详解窗口帧定义了滑动窗口的范围是高级窗口函数的关键。语法{ROWS|RANGE }BETWEENframe_startANDframe_end-- frame_start 可以是UNBOUNDEDPRECEDING-- 从分区第一行开始NPRECEDING-- 当前行前 N 行CURRENTROW-- 当前行-- frame_end 可以是CURRENTROW-- 到当前行NFOLLOWING-- 当前行后 N 行UNBOUNDEDFOLLOWING-- 到分区最后一行常见窗口帧模式模式写法用途累计到当前ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW累计求和移动窗口ROWS BETWEEN 6 PRECEDING AND CURRENT ROW7 日移动平均中心滑动ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING平滑算法到末尾ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING剩余累计-- 累计求和从开始到当前SUM(amount)OVER(ORDERBYdateROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW)-- 7日移动平均AVG(amount)OVER(ORDERBYdateROWSBETWEEN6PRECEDINGANDCURRENTROW)-- 未来3天预测基准AVG(amount)OVER(ORDERBYdateROWSBETWEENCURRENTROWAND3FOLLOWING) 不同数据库的差异特性MySQL 8.0PostgreSQLSQL ServerOracle窗口函数支持✅ 完整✅ 完整✅ 完整✅ 完整窗口帧 ROWS/RANGE✅✅✅✅PERCENT_RANK✅✅✅✅窗口函数在 UPDATE 中❌✅✅✅命名窗口❌✅✅✅MySQL 8.0 前的替代方案使用变量-- MySQL 5.7 模拟 ROW_NUMBER()SELECTname,salary,row_num:row_num1ASrow_numFROMemployees,(SELECTrow_num:0)rORDERBYsalaryDESC;⚡ 性能优化建议1. 合理使用 PARTITION BY-- ✅ 好分区字段有索引ROW_NUMBER()OVER(PARTITIONBYdepartment_idORDERBYsalaryDESC)-- ❌ 差分区过多或分区字段无索引可能导致大量排序2. 减少不必要的窗口函数-- ❌ 同一窗口重复计算SELECTROW_NUMBER()OVER(ORDERBYsalary)ASrn1,RANK()OVER(ORDERBYsalary)ASrn2FROMemployees;-- ✅ 使用命名窗口部分数据库支持SELECTROW_NUMBER()OVERwASrn1,RANK()OVERwASrn2FROMemployees WINDOW wAS(ORDERBYsalary);3. 使用索引优化-- 窗口函数需要排序创建相应索引CREATEINDEXidx_dept_salaryONemployees(department_id,salaryDESC);4. 避免大窗口下的 ROWS BETWEEN-- 大表避免使用过大的窗口范围-- ROWS BETWEEN 1000 PRECEDING AND CURRENT ROW 可能很慢 实际业务场景场景窗口函数方案排行榜ROW_NUMBER() OVER (ORDER BY score DESC)分组 Top NROW_NUMBER() OVER (PARTITION BY category ORDER BY score DESC)累计统计SUM(amount) OVER (ORDER BY date)环比/同比LAG(amount) OVER (ORDER BY date)移动平均AVG(amount) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)去重保留最新ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC)用户行为序列LAG(page) OVER (PARTITION BY session_id ORDER BY event_time) 总结问题答案窗口函数是什么在保持行数不变的情况下对每一行进行窗口内计算核心语法是什么函数() OVER (PARTITION BY ... ORDER BY ... 窗口帧)什么时候用排名、累计、移动平均、环比同比、分组 Top N与 GROUP BY 的区别GROUP BY 合并行窗口函数保留行性能如何比子查询/自连接快但需要合理使用索引
延伸阅读

更多相关文章

2026/10/23 18:52:57

《雾雾恋综》本地大模型驱动的剧本文案生产线搭建指南

《雾雾恋综》这个项目,第一眼看上去更像一部网文或者短剧选题:双女主、恋综、悬念感。但真正让我感兴趣的是,它能不能不再靠人工逐段憋稿,而是变成一条可由本地大模型驱动的剧本文案生产线。这篇文章就围绕这个题材,拆…

2026/11/4 13:34:28

基于AT89C51与Proteus仿真的多功能电子琴设计与实现

简介:本资源是一套基于AT89C51单片机的C语言多功能电子琴系统完整开发包,面向嵌入式初学者、单片机课程设计学生及Proteus仿真爱好者,解决从硬件建模、音阶生成到人机交互实现的一体化实践难题。压缩包共23个文件,含4个C源码&…

2026/11/3 4:18:58

COC跑团熟肉制作全指南:从音轨提取到硬字幕压制

说到 COC 跑团视频里的“熟肉”,很多观众的第一印象是字幕菌真伟大,第二印象可能就是:这个视频怎么还不更新?实际做过熟肉的人才会明白,最折磨人的往往不是翻译本身,而是从生肉到熟肉这条工具链上随时可能冒…

2026/11/5 13:25:11

基于ADS122U04IPWR与STM32F427ZI的工业测温方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 13:20:10

Dubbo服务下线实时告警:基于ZooKeeper Watch的轻量级监控方案

简介:这是一套面向Java分布式系统运维与开发人员的Dubbo服务高可用监控解决方案,聚焦于Provider异常下线的实时感知与告警响应。资源通过Zookeeper监听机制实现服务状态变更捕获,结合邮件通知模块,在不侵入原有Dubbo代码的前提下&…

2026/11/5 13:20:10

SSM超市管理系统源码解析:从分层架构到本地部署与业务修改

简介:这份资源是面向高校计算机专业学生与Java初学者的一套SSM框架课程设计完整项目,围绕超市管理场景,帮助读者完成从框架整合到业务模块落地的实战练习,适合作为毕业设计或课程作业的参考方案。压缩包共792个文件,约…

2026/11/5 13:20:10

SSM超市管理系统实战:从课设跑通到二次开发全解析

简介:这份资源是面向高校计算机相关专业学生与Java入门开发者的SSM课程设计参考项目,围绕超市管理场景,解决商品、库存、销售等业务模块从设计到落地的实践需求,适合作为课程作业、毕业设计原型或SSM框架练手案例。压缩包共792个文…

2026/11/5 13:15:07

PIPE4.3.0安装排错:JDK版本、JAVA_HOME与Petri验证

简介:PIPE 4.3.0 是一款基于 Petri 网的图形化建模与仿真软件,面向软件工程、系统分析与教学实验场景,帮助读者完成并发、同步与竞争等系统行为的建模、动态仿真及性质分析。压缩包共 2391 个文件,约 28.43MB,包含大量…

2026/11/5 13:15:07

用栈实现队列:双栈结构与工程实践

1. 栈与队列的相爱相杀第一次看到这个题目时,我正坐在星巴克啃着牛角包。用栈实现队列?这就像用筷子喝汤——不是不行,但总觉得哪里怪怪的。栈和队列这对数据结构里的欢喜冤家,一个后进先出(LIFO)&#xff…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑