Oracle 开窗函数

在 Oracle 数据库中,开窗函数(Window Functions)是一类非常强大的 SQL 函数,用于在结果集的"窗口"上执行计算。这些窗口函数允许你在查询的每一行上执行聚合操作(如求和、平均、计数等),同时保留原始行的详细数据。

以下是一些常见的 Oracle 开窗函数及其用法:

1. ROW_NUMBER()

为结果集中的每一行分配一个唯一的序号。

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank_in_dept 
FROM 
employees;

2. RANK()

类似于 ROW_NUMBER(),但如果有相同的值,它们会共享相同的排名,并且后续排名会跳过。

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank_in_dept 
FROM 
employees;

3. DENSE_RANK()

类似于 RANK(),但后续排名不会跳过。

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dense_rank_in_dept 
FROM 
employees;

4. NTILE(n)

将结果集划分为 n 个桶,并为每一行分配一个桶号。

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
NTILE(4) OVER (PARTITION BY department_id ORDER BY salary DESC) AS quartile 
FROM 
employees;

5. LAG() 和 LEAD()

用于访问结果集中当前行的前一行或后一行的数据。

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
LAG(salary, 1) OVER (PARTITION BY department_id ORDER BY salary) AS prev_salary, 
LEAD(salary, 1) OVER (PARTITION BY department_id ORDER BY salary) AS next_salary 
FROM 
employees;

6. FIRST_VALUE() 和 LAST_VALUE()

返回窗口框架中的第一行或最后一行的值。

sql 复制代码
SELECT

employee_id,

department_id,

salary,

FIRST_VALUE(salary) OVER (PARTITION BY department_id ORDER BY salary RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_salary_in_dept,

LAST_VALUE(salary) OVER (PARTITION BY department_id ORDER BY salary RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_salary_in_dept

FROM

employees;

7. SUM(), AVG(), MIN(), MAX() 等聚合函数

在窗口上执行常见的聚合操作。

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
SUM(salary) OVER (PARTITION BY department_id ORDER BY salary RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_salary 
FROM 
employees;

窗口子句(Window Clause)

在开窗函数中,OVER 子句用于定义窗口的分区和排序。PARTITION BY 子句用于将结果集划分为分区,ORDER BY 子句用于定义每个分区内的排序顺序。

sql 复制代码
OVER ( 
[PARTITION BY partition_expression, ...] 
[ORDER BY sort_expression [ASC|DESC], ...] 
[ROWS|RANGE BETWEEN frame_start AND frame_end] 
)
  • PARTITION BY:将结果集划分为多个分区,每个分区独立计算。
  • ORDER BY:定义每个分区内的排序顺序。
  • ROWSRANGE:定义窗口框架(frame),即窗口内包含的行范围。

示例:综合使用

sql 复制代码
SELECT 
employee_id, 
department_id, 
salary, 
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank_in_dept, 
SUM(salary) OVER (PARTITION BY department_id ORDER BY salary RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_salary 
FROM 
employees;

以上示例展示了如何使用多个开窗函数,并结合 PARTITION BYORDER BY 子句进行复杂查询。

相关推荐
剩下了什么12 小时前
MySQL JSON_SET() 函数
数据库·mysql·json
山峰哥13 小时前
数据库工程与SQL调优——从索引策略到查询优化的深度实践
数据库·sql·性能优化·编辑器
较劲男子汉13 小时前
CANN Runtime零拷贝传输技术源码实战 彻底打通Host与Device的数据传输壁垒
运维·服务器·数据库·cann
java搬砖工-苤-初心不变13 小时前
MySQL 主从复制配置完全指南:从原理到实践
数据库·mysql
山岚的运维笔记15 小时前
SQL Server笔记 -- 第18章:Views
数据库·笔记·sql·microsoft·sqlserver
roman_日积跬步-终至千里16 小时前
【LangGraph4j】LangGraph4j 核心概念与图编排原理
java·服务器·数据库
汇智信科16 小时前
打破信息孤岛,重构企业效率:汇智信科企业信息系统一体化运营平台
数据库·重构
野犬寒鸦16 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
晚霞的不甘17 小时前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d
市场部需要一个软件开发岗位18 小时前
JAVA开发常见安全问题:纵向越权
java·数据库·安全