Oracle 分析函数(Analytic Functions)

Oracle 的分析函数(Analytic Functions)是一类特殊的函数,用于在查询结果的窗口(window) 内执行计算(如排名、累计求和、移动平均等),不会聚合结果行 ,而是为每一行返回一个计算结果。它们通常与 OVER() 子句结合使用,是处理复杂分析需求(如分组排名、累计统计等)的高效工具。

分析函数核心语法

analytic_function(arguments)

OVER (

PARTITION BY partition_clause -- 将数据划分为多个窗口(类似GROUP BY)

ORDER BY order_clause -- 定义窗口内的排序规则

window_clause -- 定义窗口范围(如滑动窗口)

)

常见分析函数分类

分类 函数示例 用途
排名函数 ROW_NUMBER(), RANK(), DENSE_RANK() 为行分配排名(如第1名、第2名)
聚合函数 SUM(), AVG(), COUNT(), MAX(), MIN() 计算窗口内的聚合值(如累计求和、移动平均)
偏移函数 LAG(), LEAD(), FIRST_VALUE(), LAST_VALUE() 访问窗口内其他行的数据(如前一行、后一行)
分布函数 CUME_DIST(), PERCENT_RANK(), NTILE() 计算分布相关的统计(如百分位、分桶)

经典示例

sql 复制代码
CREATE TABLE sales (
  product VARCHAR2(20),
  sale_date DATE,
  amount NUMBER
);

INSERT INTO sales VALUES ('A', DATE '2023-01-01', 100);
INSERT INTO sales VALUES ('A', DATE '2023-01-02', 200);
INSERT INTO sales VALUES ('B', DATE '2023-01-01', 150);
INSERT INTO sales VALUES ('B', DATE '2023-01-03', 300);


计算每个产品的累计销售额

SELECT 
  product,
  sale_date,
  amount,
  SUM(amount) OVER (
    PARTITION BY product 
    ORDER BY sale_date 
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS cumulative_amount
FROM sales;


PRODUCT | SALE_DATE  | AMOUNT | CUMULATIVE_AMOUNT
--------|------------|--------|-------------------
A       | 2023-01-01 | 100    | 100
A       | 2023-01-02 | 200    | 300
B       | 2023-01-01 | 150    | 150
B       | 2023-01-03 | 300    | 450
sql 复制代码
计算每个产品的销售额排名
SELECT 
  product,
  sale_date,
  amount,
  RANK() OVER (
    PARTITION BY product 
    ORDER BY amount DESC
  ) AS sales_rank
FROM sales;

PRODUCT | SALE_DATE  | AMOUNT | SALES_RANK
--------|------------|--------|-----------
A       | 2023-01-02 | 200    | 1
A       | 2023-01-01 | 100    | 2
B       | 2023-01-03 | 300    | 1
B       | 2023-01-01 | 150    | 2
sql 复制代码
获取每个产品的前一行销售额(LAG)

SELECT 
  product,
  sale_date,
  amount,
  LAG(amount, 1, 0) OVER (
    PARTITION BY product 
    ORDER BY sale_date
  ) AS prev_amount
FROM sales;

PRODUCT | SALE_DATE  | AMOUNT | PREV_AMOUNT
--------|------------|--------|------------
A       | 2023-01-01 | 100    | 0          -- 无前一行,默认0
A       | 2023-01-02 | 200    | 100
B       | 2023-01-01 | 150    | 0
B       | 2023-01-03 | 300    | 150

关键子句详解

  1. PARTITION BY

    将数据划分为多个窗口,每个窗口独立计算。类似于 GROUP BY,但不会减少行数。

  2. ORDER BY

    定义窗口内的排序规则,影响排名、累计计算等。

  3. 窗口帧(Window Frame)

    通过 ROWSRANGE 定义窗口范围,常见用法:

    • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:从第一行到当前行(累计计算)。

    • ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING:前一行到后一行(滑动窗口)。

常见问题

  1. 分析函数与聚合函数的区别?

    聚合函数(如 SUM())会合并多行为一行,而分析函数会为每一行返回结果。

  2. 如何优化分析函数性能?

    合理使用 PARTITION BY 和索引,避免全表扫描。

  3. RANK() vs DENSE_RANK() vs ROW_NUMBER()

    • RANK():允许并列排名,后续排名跳跃(如 1,1,3)。

    • DENSE_RANK():允许并列排名,后续排名连续(如 1,1,2)。

    • ROW_NUMBER():无并列,严格递增(如 1,2,3)。

相关推荐
复园电子3 小时前
企业级PDF批量盖章方案选型指南
数据库·pdf
AI-好学者10 小时前
阶段一-图数据库基础与PropertyGraph模型
数据库·rag·knowledge graph·graphrag
其实防守也摸鱼11 小时前
运维--学习阶段问题解答(1)(自测)
linux·运维·服务器·数据库·学习·自动化·命令模式
懒鸟一枚11 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
龙仔72511 小时前
SQL Server 创建只读账号完整操作(分两种场景:SSMS图形界面 + T-SQL脚本)
数据库·sql·oracle
霁月的小屋12 小时前
生产环境中的事务实践——银行系统上线记(四)
数据库
Database_Cool_12 小时前
AI 应用数据底座首选:阿里云 PolarDB 为大模型 RAG 提供一体化支撑
数据库·阿里云
玖玥拾12 小时前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
IvorySQL13 小时前
PG 日报|社区讨论重构 pg_hba 配置文件格式
数据库·人工智能·postgresql·重构·ivorysql
逝水无殇13 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#