尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Oracle窗口函数

Oracle窗口函数
📅 发布时间:2026/6/19 19:48:29

Oracle窗口函数是SQL中极其强大的工具,它允许你在不折叠分组行的前提下,对一组相关的行(一个“窗口”)进行计算。理解它能将你的数据分析能力提升一个维度。

一、核心概念:它是什么?

想象一下普通的GROUP BY:它将多行合并成一行。窗口函数恰恰相反:它为查询结果的每一行都返回一个值,这个值是基于与该行相关的一组行计算而来的。

关键区别:

  • GROUP BY + 聚合函数:多行输入,一行输出(每个分组)。
  • 窗口函数 + 聚合/分析函数:多行输入,多行输出(每行都附加计算结果)。

二、核心语法结构

function_name([arguments]) 
OVER ([PARTITION BY partition_expression, ...]  -- 定义窗口分区(分组)[ORDER BY sort_expression [ASC | DESC], ...] -- 定义窗口内排序[ROWS/RANGE window_frame_clause] -- 定义窗口框架(计算范围)
)

三、三大核心组成部分详解

1. PARTITION BY

将整个结果集划分为更小的、独立的“窗口”或分区。计算在每个分区内独立进行。

  • 示例:PARTITION BY department_id 会按部门创建独立窗口。

2. ORDER BY

定义窗口内行的顺序。这对于排名、累计计算等至关重要。

  • 示例:ORDER BY sale_date DESC 会让窗口按销售日期降序排列。

3. 窗口框架 (ROWS/RANGE)

当使用ORDER BY时,可以进一步限定计算的具体范围。这是窗口函数最精细的控制部分。

  • ROWS:基于物理行的偏移。
    • ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING:当前行、前一行、后一行。
    • ROWS UNBOUNDED PRECEDING:从分区第一行到当前行(常用于累计)。
  • RANGE:基于ORDER BY列的值的逻辑偏移。
    • RANGE BETWEEN INTERVAL '1' DAY PRECEDING AND CURRENT ROW:值在(当前日期-1天)到当前日期之间的所有行。

四、常用窗口函数分类与示例

我们用一个员工薪资表 emp_salary 来举例:

EMP_ID NAME DEPT SALARY HIRE_DATE
101 张三 销售 8000 2020-01-01
102 李四 销售 9000 2019-06-01
103 王五 技术 12000 2021-03-01
104 赵六 技术 11000 2020-08-01
105 钱七 销售 8500 2021-05-01

1. 排名函数

ROW_NUMBER():连续的、唯一的序号(即使值相同)。

SELECT emp_id, name, dept, salary,ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) as dept_salary_rank_row
FROM emp_salary;

结果:技术部,王五(12000)排1,赵六(11000)排2。销售部,李四(9000)排1,钱七(8500)排2,张三(8000)排3。

RANK() 与 DENSE_RANK():处理并列排名。

  • RANK():并列会占用名次。如:1, 2, 2, 4, ...
  • DENSE_RANK():并列不占用名次。如:1, 2, 2, 3, ...

2. 聚合函数(用作窗口函数)

SUM(), AVG(), COUNT(), MAX(), MIN()

SELECT emp_id, name, dept, salary,SUM(salary) OVER (PARTITION BY dept) as dept_total_salary, -- 部门总薪资AVG(salary) OVER (PARTITION BY dept) as dept_avg_salary,   -- 部门平均薪资SUM(salary) OVER (PARTITION BY dept ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as dept_cumulative_salary -- 部门按入职累计薪资
FROM emp_salary;

3. 分布函数

PERCENT_RANK():(当前行的RANK值 - 1) / (总行数 - 1),结果在0~1之间。
CUME_DIST():小于等于当前行值的行数 / 分区总行数。

4. 前后行取值函数(极其实用)

LAG(column, n):获取窗口内当前行之前第n行的值。
LEAD(column, n):获取窗口内当前行之后第n行的值。

-- 查看每位员工与其部门内上一名员工的薪资差
SELECT emp_id, name, dept, salary,LAG(salary, 1) OVER (PARTITION BY dept ORDER BY salary) as prev_salary,salary - LAG(salary, 1) OVER (PARTITION BY dept ORDER BY salary) as salary_diff
FROM emp_salary;

5. 首尾取值函数

FIRST_VALUE(column):返回窗口第一行的值。
LAST_VALUE(column):返回窗口最后一行的值。
注意:使用LAST_VALUE时,通常需要指定完整的窗口框架,否则默认范围是RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,可能不是你想要的结果。

五、一个综合性的复杂示例

-- 查询:找出每个部门薪资排名前2的员工,并展示该员工薪资与部门最高、平均薪资的对比,以及比部门内上一位入职员工的薪资增长情况。
SELECT dept,name,salary,hire_date,dept_salary_rank,dept_max_salary,ROUND(salary / dept_avg_salary * 100, 2) || '%' as vs_avg_pct, -- 薪资 vs 部门平均salary - prev_emp_salary as salary_increase_from_prev -- 比前一位员工高多少
FROM (SELECT dept,name,salary,hire_date,ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) as dept_salary_rank,MAX(salary) OVER (PARTITION BY dept) as dept_max_salary,AVG(salary) OVER (PARTITION BY dept) as dept_avg_salary,LAG(salary, 1) OVER (PARTITION BY dept ORDER BY hire_date) as prev_emp_salaryFROM emp_salary
)
WHERE dept_salary_rank <= 2
ORDER BY dept, dept_salary_rank;

六、性能与最佳实践要点

  1. 性能:窗口函数通常在数据库内部进行优化,性能远优于使用自连接或相关子查询实现相同逻辑。但复杂的窗口框架(尤其是RANGE)可能开销较大。
  2. 索引是朋友:在PARTITION BY和ORDER BY涉及的列上建立索引,能大幅提升窗口函数的执行速度。
  3. 执行顺序:记住,窗口函数是在WHERE, GROUP BY, HAVING子句之后执行的。因此,你不能在WHERE子句中直接引用窗口函数别名。如果需要过滤窗口函数结果,必须使用子查询或WITH(CTE)。
  4. 适用版本:Oracle 8i开始引入基础分析函数,后续版本功能不断增强。本文所述功能在Oracle 9i及以上版本均支持,部分高级功能(如LISTAGG)在11g后更完善。

窗口函数初看复杂,但它是编写清晰、高效分析SQL的基石。建议你从ROW_NUMBER()和SUM() OVER (PARTITION BY ...)开始练习,逐步尝试LAG/LEAD和窗口框架,很快就能掌握其精髓。

相关新闻

  • 软件推荐:Beyond.Compare.v3.3.13.18981 文本对比软件
  • 2025年杭州艺术学校TOP5推荐:杭州艺术学校靠谱的美术中 - 工业推荐榜
  • 2025年度靠谱的超级电容生产商TOP5权威推荐:看哪家售后 - myqiye

最新新闻

  • 高中/高三/高考 回忆录
  • 从晶体管到可编程单元:深入解析FPGA芯片的架构层次与设计哲学
  • 02 代码整洁之道阅读笔记
  • 2026年卫生间漏水维修服务适配指南:昆山鼎壹万防水补漏公司及苏州本地服务商综合适配解析 专业防水公司排名推荐(2026年6月防水补漏最新TOP权威排名) - 鼎壹万修缮说
  • Onekey完整教程:一键解锁Steam游戏DLC的终极方案
  • 2026年南京知名3D效果图制作公司大盘点,你知道几家?

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号