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

Oracle窗口函数

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 BYORDER 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和窗口框架,很快就能掌握其精髓。

http://www.rkmt.cn/news/82167.html

相关文章:

  • 软件推荐:Beyond.Compare.v3.3.13.18981 文本对比软件
  • 2025年杭州艺术学校TOP5推荐:杭州艺术学校靠谱的美术中 - 工业推荐榜
  • 2025年度靠谱的超级电容生产商TOP5权威推荐:看哪家售后 - myqiye
  • 2025年杭州会议室全彩屏本地服务商推荐:靠谱的本地会议室全 - 工业品牌热点
  • 2025-2026年恒温恒湿试验箱十大厂家盘点,涵盖高低温试验箱/冷热冲击试验箱供应商,带您快速了解行业内的优质品牌与核心优势 - 品牌推荐大师1
  • windriver 第8章:调试驱动程序
  • visual studio提示使用100缩放放比例重新启动
  • 2025年中国铝合金精密管材品牌制造商推荐:电子用铝合金精密 - myqiye
  • 2025年热门的大型排油烟机清洗厂家最新用户好评榜 - 行业平台推荐
  • 2025年高品质铝合金精密管材五大推荐制造商,看哪家售后优? - myqiye
  • 2025年五大中医智能装备定制厂家排行榜,中医智能装备正规厂 - mypinpai
  • 常熟国强和茂管材有限公司产品的市场认可度高吗?质量如何? - myqiye
  • MAF快速入门(6)混合编排工作流
  • 2025年五大实力强的超级电容企业推荐,国内知名超级电容联系 - 工业品牌热点
  • 2025山东功能性食品企业TOP5权威推荐:深度解析山东佰诺 - 工业推荐榜
  • 2025年东北中医智能装备工厂推荐排行榜,服务不错的中医智能 - mypinpai
  • 2025年知名的养猪场除臭设备厂家质量评选榜(可靠) - 行业平台推荐
  • 2025靠谱单温/不锈钢/对开门防爆冰箱TOP5推荐:工业存 - myqiye
  • Flask 应用部署实战:Nginx 反向代理配置指南
  • 聚焦江西过碳酸钠生产厂,这些企业凭实力领跑市场 - 品牌2026
  • 喵喵喵 X
  • FIRE之旅 财务计算器:金融独立模型中的复利可视化与敏感性分析 - 详解
  • 2025年靠谱的光伏车棚安装/BIPV 光伏车棚行业应用示范榜 - 行业平台推荐
  • 2025年评价高的光伏防水屋面厂家选购指南与推荐 - 行业平台推荐
  • 2025年下半年四川实木楼梯电话哪家好?前十推荐 - 2025年11月品牌推荐榜
  • 2025年下半年四川实木楼梯电话优质服务商推荐解析 - 2025年11月品牌推荐榜
  • 2025年下半年四川实木楼梯品牌综合推荐与选购指南 - 2025年11月品牌推荐榜
  • 2025年下半年四川电动旗杆品牌选购指南:前五推荐与比较 - 2025年11月品牌推荐榜
  • 2025年热门的BIPV屋面改造/BIPV光伏支架行业内口碑厂家排行榜 - 行业平台推荐
  • 2025年比较好的光伏屋顶设计热门厂家推荐榜单 - 行业平台推荐