当前位置: 首页 > 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.jsqmd.com/news/71632/

相关文章:

  • Error running Application.Command line is too long
  • 2025年工业防爆除湿机厂家排行榜,看哪家口碑好、技术强? - mypinpai
  • 软件推荐:Beyond.Compare.v3.3.13.18981 文本对比软件
  • 2025年实力强的超级电容制造企业TOP5:国内知名制造商权 - myqiye
  • 2025年杭州会议室全彩屏五大靠谱货源渠道推荐,包安装维护服 - 工业品牌热点
  • 负载均衡相关的upstream模块参数
  • 2025年杭州艺术学校TOP5推荐:杭州艺术学校靠谱的美术中 - 工业推荐榜
  • 2025年移动工业防爆除湿机厂家排名,靠谱防爆除湿机品牌推荐 - mypinpai
  • 2025年杭州会议室全彩屏本地服务商推荐:靠谱的本地会议室全 - 工业品牌热点
  • 中小企业ChatBI实施完整指南:从选型到落地
  • 2025-2026年恒温恒湿试验箱十大厂家盘点,涵盖高低温试验箱/冷热冲击试验箱供应商,带您快速了解行业内的优质品牌与核心优势 - 品牌推荐大师1
  • Python 机器学习入门实战:客户流失预测任务全教程
  • windriver 第8章:调试驱动程序
  • 2025年质量好的酒店油烟管道清洗厂家质量评选榜(可靠) - 行业平台推荐
  • visual studio提示使用100缩放放比例重新启动
  • 2025年口碑好的双温防爆冰箱生产商推荐:看哪家产品质量好 - mypinpai
  • 2025年质量好的酒店油烟管道清洗/厨房油烟管道清洗厂家采购指南榜(选购必看) - 品牌宣传支持者
  • 2025年中国铝合金精密管材品牌制造商推荐:电子用铝合金精密 - myqiye
  • 2025年五大药食同源特殊膳食OEM厂家排行榜,看哪家靠谱? - 工业品牌热点
  • 2025年热门的大型排油烟机清洗厂家最新用户好评榜 - 行业平台推荐
  • 2025年五大胶原蛋白肽特殊膳食oem公司排行榜 - 工业推荐榜
  • 2025年值得推荐的珠江电缆厂家TOP5排行榜,看哪家产品质 - mypinpai
  • 2025年高品质铝合金精密管材五大推荐制造商,看哪家售后优? - myqiye
  • 压片糖果代加工哪家好?压片糖果代加工生产厂哪家专业? - 工业品牌热点
  • 压片糖果代加工哪家好?哪家技术实力强?求推荐 - 工业推荐榜
  • 2025年靠谱的餐饮店油烟机清洗厂家选购指南与推荐 - 品牌宣传支持者
  • windriver 第7章:开发驱动程序
  • 国内专业全自动超纯水设备/水处理设备/反渗透设备生产厂家品牌推荐,可提供定制服务 - 品牌推荐大师1
  • 2025年五大中医智能装备定制厂家排行榜,中医智能装备正规厂 - mypinpai
  • 常熟国强和茂管材有限公司产品的市场认可度高吗?质量如何? - myqiye