Oracle 19C 内置聚合函数开发与使用文档

1. 引言

聚合函数(Aggregate Functions)是 Oracle 数据库中用于对一组数据进行汇总计算并返回单一结果的函数。它们广泛应用于数据分析、报表生成和统计计算等场景。Oracle 19C 提供了丰富的内置聚合函数,从基本的求和、平均值计算到复杂的统计分析和字符串聚合功能。

本文档详细介绍 Oracle 19C 中常用的聚合函数,包括其语法、功能、使用示例及性能优化建议,旨在帮助开发人员高效地进行数据聚合相关的开发工作。

2. 基本聚合函数

2.1 SUM

  • 功能:计算数值列的总和
  • 语法SUM([DISTINCT | ALL] expr)
  • 参数
    • DISTINCT:可选,仅对不同的值求和
    • ALL:可选,对所有值求和(默认)
  • 返回类型:NUMBER
  • 示例

    sql

    -- 计算所有员工的工资总和
    SELECT SUM(salary) AS 总工资 FROM employees;
    
    -- 计算不同部门的工资总和
    SELECT department_id, SUM(salary) AS 部门总工资
    FROM employees
    GROUP BY department_id
    ORDER BY department_id;
    
    -- 计算不同工资值的总和(忽略重复值)
    SELECT SUM(DISTINCT salary) AS 不同工资总和 FROM employees;
    
  • 注意事项:忽略 NULL 值;如果所有值都是 NULL,返回 NULL

2.2 AVG

  • 功能:计算数值列的平均值
  • 语法AVG([DISTINCT | ALL] expr)
  • 示例

    sql

    -- 计算所有员工的平均工资
    SELECT AVG(salary) AS 平均工资 FROM employees;
    
    -- 按部门计算平均工资
    SELECT department_id, AVG(salary) AS 部门平均工资
    FROM employees
    GROUP BY department_id
    HAVING AVG(salary) > 6000
    ORDER BY 2 DESC;
    
  • 注意事项:计算方式为总和除以非 NULL 值的数量

2.3 COUNT

  • 功能:计算记录数量
  • 语法
    • COUNT(*):计算所有行的数量,包括 NULL 值
    • COUNT(expr):计算表达式非 NULL 值的数量
    • COUNT(DISTINCT expr):计算表达式不同非 NULL 值的数量
  • 示例

    sql

    -- 计算员工总数(包括所有行)
    SELECT COUNT(*) AS 员工总数 FROM employees;
    
    -- 计算有佣金的员工数量
    SELECT COUNT(commission_pct) AS 有佣金的员工数 FROM employees;
    
    -- 计算不同部门的数量
    SELECT COUNT(DISTINCT department_id) AS 部门数量 FROM employees;
    

2.4 MAX

  • 功能:返回列中的最大值
  • 语法MAX(expr)
  • 支持的数据类型:数值型、字符型、日期型等
  • 示例

    sql

    -- 查找最高工资
    SELECT MAX(salary) AS 最高工资 FROM employees;
    
    -- 查找每个部门的最高工资和对应的员工
    SELECT department_id, MAX(salary) AS 部门最高工资,
           MAX(last_name) KEEP (DENSE_RANK FIRST ORDER BY salary DESC) AS 最高工资员工
    FROM employees
    GROUP BY department_id;
    
    -- 查找最近的雇佣日期
    SELECT MAX(hire_date) AS 最近雇佣日期 FROM employees;
    

2.5 MIN

  • 功能:返回列中的最小值
  • 语法MIN(expr)
  • 示例

    sql

    -- 查找最低工资
    SELECT MIN(salary) AS 最低工资 FROM employees;
    
    -- 查找每个部门最早雇佣的员工
    SELECT department_id, MIN(hire_date) AS 最早雇佣日期
    FROM employees
    GROUP BY department_id;
    

3. 统计聚合函数

3.1 STDDEV 和 STDDEV_POP

  • 功能:计算总体标准差
  • 语法STDDEV(expr)STDDEV_POP(expr)
  • 示例

    sql

    -- 计算工资的标准差
    SELECT STDDEV(salary) AS 工资标准差 FROM employees;
    

3.2 STDDEV_SAMP

  • 功能:计算样本标准差
  • 语法STDDEV_SAMP(expr)

3.3 VARIANCE 和 VAR_POP

  • 功能:计算总体方差
  • 语法VARIANCE(expr)VAR_POP(expr)

3.4 VAR_SAMP

  • 功能:计算样本方差
  • 语法VAR_SAMP(expr)

3.5 MEDIAN

  • 功能:计算中位数
  • 语法MEDIAN(expr)
  • 示例

    sql

    -- 计算工资中位数
    SELECT MEDIAN(salary) AS 工资中位数 FROM employees;
    
  • 注意事项:MEDIAN 是一个分析函数,也可作为聚合函数使用,返回中间值或中间两个值的平均值

3.6 PERCENTILE_CONT

  • 功能:计算连续分布的百分位数
  • 语法PERCENTILE_CONT(percentile) WITHIN GROUP (ORDER BY expr)
  • 示例

    sql

    -- 计算工资的75百分位数
    SELECT PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY salary) AS 75分位工资
    FROM employees;
    

3.7 PERCENTILE_DISC

  • 功能:计算离散分布的百分位数
  • 语法PERCENTILE_DISC(percentile) WITHIN GROUP (ORDER BY expr)

4. 字符串聚合函数

4.1 LISTAGG

  • 功能:将多行字符串连接成单行字符串
  • 语法LISTAGG(expr, delimiter) [WITHIN GROUP (ORDER BY order_expr)] [OVER (query_partition_clause)]
  • 示例

    sql

    -- 按部门聚合员工姓名,用逗号分隔
    SELECT department_id,
           LISTAGG(last_name, ', ') WITHIN GROUP (ORDER BY last_name) AS 员工列表
    FROM employees
    GROUP BY department_id
    ORDER BY department_id;
    
    -- 限制聚合结果长度
    SELECT department_id,
           LISTAGG(last_name, ', ') WITHIN GROUP (ORDER BY last_name) 
           ON OVERFLOW TRUNCATE '...' AS 员工列表
    FROM employees
    GROUP BY department_id;
    
  • Oracle 19C 新特性:支持ON OVERFLOW子句处理结果过长的情况,可选择错误或截断

4.2 STRAGG

  • 功能:字符串聚合(Oracle 内部函数,建议使用 LISTAGG)
  • 注意事项:非官方支持函数,行为可能随版本变化

5. 高级聚合函数

5.1 COLLECT

  • 功能:将列值收集到集合中
  • 语法COLLECT(expr)
  • 示例

    sql

    -- 创建集合类型
    CREATE TYPE num_tab AS TABLE OF NUMBER;
    
    -- 收集每个部门的员工ID
    SELECT department_id, COLLECT(employee_id) AS 员工ID集合
    FROM employees
    GROUP BY department_id;
    

5.2 JSON_ARRAYAGG

  • 功能:将结果集聚合为 JSON 数组
  • 语法JSON_ARRAYAGG(expr [FORMAT JSON] [ORDER BY sort_expr] [NULL ON NULL])
  • 示例

    sql

    -- 生成部门员工的JSON数组
    SELECT department_id,
           JSON_ARRAYAGG(
             JSON_OBJECT(
               'id' VALUE employee_id,
               'name' VALUE last_name,
               'salary' VALUE salary
             ) ORDER BY last_name
           ) AS 员工信息
    FROM employees
    GROUP BY department_id;
    

5.3 JSON_OBJECTAGG

  • 功能:将结果集聚合为 JSON 对象
  • 语法JSON_OBJECTAGG(key_expr VALUE value_expr [FORMAT JSON] [ORDER BY sort_expr])

5.4 XMLAGG

  • 功能:将结果集聚合为 XML 元素
  • 语法XMLAGG(XMLELEMENT(name, expr) [ORDER BY sort_expr])
  • 示例

    sql

    -- 生成部门员工的XML
    SELECT department_id,
           XMLAGG(
             XMLELEMENT("employee", 
               XMLATTRIBUTES(employee_id AS "id"),
               last_name
             ) ORDER BY last_name
           ) AS 员工XML
    FROM employees
    GROUP BY department_id;
    

6. 分组扩展函数

6.1 ROLLUP

  • 功能:生成多层级的聚合结果,从最细粒度到总计
  • 语法GROUP BY ROLLUP(expr1, expr2, ...)
  • 示例

    sql

    -- 按部门和职位进行ROLLUP聚合
    SELECT department_id, job_id, COUNT(*), SUM(salary)
    FROM employees
    GROUP BY ROLLUP(department_id, job_id)
    ORDER BY department_id, job_id;
    
  • 结果说明:返回每个部门每个职位的聚合、每个部门的总计、以及整体总计

6.2 CUBE

  • 功能:生成所有可能组合的聚合结果
  • 语法GROUP BY CUBE(expr1, expr2, ...)
  • 示例

    sql

    -- 按部门和职位进行CUBE聚合
    SELECT department_id, job_id, COUNT(*), SUM(salary)
    FROM employees
    GROUP BY CUBE(department_id, job_id)
    ORDER BY department_id, job_id;
    
  • 与 ROLLUP 的区别:CUBE 生成所有维度组合的聚合,而 ROLLUP 只生成层级式的聚合

6.3 GROUPING SETS

  • 功能:指定需要聚合的列组合
  • 语法GROUP BY GROUPING SETS((expr1, expr2), (expr3), ...)
  • 示例

    sql

    -- 按指定组合进行聚合
    SELECT department_id, job_id, manager_id, SUM(salary)
    FROM employees
    GROUP BY GROUPING SETS(
      (department_id, job_id),  -- 部门+职位的聚合
      (department_id, manager_id),  -- 部门+经理的聚合
      ()  -- 总计
    );
    

6.4 GROUPING 和 GROUPING_ID

  • 功能:标识聚合行的分组级别
  • 语法GROUPING(expr)GROUPING_ID(expr1, expr2, ...)
  • 示例

    sql

    -- 使用GROUPING标识聚合行
    SELECT 
      department_id,
      job_id,
      GROUPING(department_id) AS dept_group_flag,
      GROUPING(job_id) AS job_group_flag,
      SUM(salary) AS 总工资
    FROM employees
    GROUP BY ROLLUP(department_id, job_id);
    
  • 返回值:GROUPING 返回 1 表示该行是该列的聚合行,0 表示是细节行

7. 聚合函数与空值处理

  1. NULL 值处理规则

    • 所有聚合函数都会自动忽略 NULL 值
    • COUNT (*) 是例外,它会计算包含 NULL 值的行
  2. 处理 NULL 的示例

    sql

    -- 计算平均佣金(自动忽略NULL)
    SELECT AVG(commission_pct) AS 平均佣金比例 FROM employees;
    
    -- 将NULL视为0进行计算
    SELECT AVG(NVL(commission_pct, 0)) AS 平均佣金比例(含0) FROM employees;
    
  3. 使用 COALESCE 处理多列 NULL

    sql

    -- 计算多个绩效指标的平均值,将NULL替换为0
    SELECT AVG(COALESCE(performance_score, 0)) AS 平均绩效
    FROM employee_performance;
    

8. 聚合函数与分析函数的区别

特性聚合函数分析函数
结果行数通常返回单行或按组返回较少行保留原始行数,每行都有聚合结果
使用方式与 GROUP BY 配合使用使用 OVER () 子句
典型用途生成汇总报表每行数据附加聚合信息(如累计和)

示例对比:

sql

-- 聚合函数:每个部门返回一行
SELECT department_id, AVG(salary) AS 部门平均工资
FROM employees
GROUP BY department_id;

-- 分析函数:保留所有行,附加部门平均工资
SELECT employee_id, last_name, department_id, salary,
       AVG(salary) OVER (PARTITION BY department_id) AS 部门平均工资
FROM employees;

9. 性能考虑与最佳实践

9.1 索引优化

  • 为 GROUP BY 和聚合函数中使用的列创建适当的索引
  • 考虑创建复合索引,包含 GROUP BY 列和聚合列
  • 示例:

    sql

    -- 为分组和聚合列创建索引
    CREATE INDEX idx_emp_dept_salary ON employees(department_id, salary);
    

9.2 过滤先行

  • 在聚合前尽量过滤数据,减少聚合的数据量
  • 优先使用 WHERE 子句过滤,其次使用 HAVING 子句

    sql

    -- 推荐:先过滤再聚合
    SELECT department_id, SUM(salary)
    FROM employees
    WHERE hire_date > TO_DATE('2020-01-01', 'YYYY-MM-DD')
    GROUP BY department_id;
    

9.3 避免不必要的 DISTINCT

  • DISTINCT 会增加计算开销,确认确实需要去重时再使用
  • 比较:

    sql

    -- 开销较大
    SELECT SUM(DISTINCT salary) FROM employees;
    
    -- 如果不需要去重,使用更高效的方式
    SELECT SUM(salary) FROM employees;
    

9.4 处理大型数据集

  • 对于超大型数据集,考虑使用并行查询

    sql

    SELECT /*+ PARALLEL(employees, 4) */
           department_id, SUM(salary)
    FROM employees
    GROUP BY department_id;
    
  • 考虑使用物化视图预先计算聚合结果

9.5 LISTAGG 性能优化

  • 对大型数据集使用 LISTAGG 时,设置适当的 MAX_STRING_SIZE
  • 使用 ON OVERFLOW 子句避免溢出错误
  • 考虑分批次聚合长字符串

9.6 避免在聚合函数中使用复杂表达式

  • 将复杂表达式提前计算或使用虚拟列

    sql

    -- 不推荐:聚合函数中包含复杂计算
    SELECT SUM(salary * 1.15 * (1 + NVL(commission_pct, 0))) FROM employees;
    
    -- 推荐:使用子查询提前计算
    SELECT SUM(total_compensation)
    FROM (
      SELECT salary * 1.15 * (1 + NVL(commission_pct, 0)) AS total_compensation
      FROM employees
    );
    

10. 总结

Oracle 19C 提供了丰富的内置聚合函数,从基本的 SUM、AVG 到高级的 LISTAGG、JSON_ARRAYAGG,再到分组扩展的 ROLLUP、CUBE 等,满足了各种数据聚合和分析需求。

掌握这些聚合函数的使用方法,能够帮助开发人员高效地生成汇总报表、进行数据分析和统计计算。在实际应用中,应根据具体业务场景选择合适的聚合函数,并遵循性能优化最佳实践,特别是在处理大型数据集时。

通过合理使用聚合函数和分组技术,可以显著简化 SQL 代码,提高开发效率,同时保证查询性能,为业务决策提供有力的数据支持。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值