zoukankan      html  css  js  c++  java
  • 【Oracle】Oracle分析函数详解

    Oracle数据库中的函数有多种,比如单行函数、聚合函数、对象引用函数、模型函数、OLAP函数等。本篇将详细介绍Oracle数据库中的分析函数。

    一 分析函数概述

    所谓分析函数,是基于一组数据行计算聚合值,其与聚合函数的不同之处在于,它为每一组返回多个数据行。一组数据行称为一个窗口,由analytic_clause子句进行定义,对于每一行,定义一个行移动窗口,窗口确定用于为当前行执行计算的行的范围,它的大小可以基于物理行或逻辑间隔(如时间)。

    二 分析函数语法

    说明:

    analytic_function

    指出分析函数的名称;

    arguments

    分析函数的参数,参数数量在0个到3个之间,该参数类型可以是任何数值数据类型,或者任何可以隐式转换为数值数据类型的非数值类型。

    analytic_clause

    使用OVER analytic_clause子句展示在查询结果集上所进行的函数操作,该子句是在FROM、WHERE、GROUP BY和HAVING子句后进行计算的。

     使用PARTITION BY子句可以基于一个或多个expr将查询结果集划分为多个组,如果忽略该子句,则函数会将整个查询结果集当做一个组。

    order_by_clause子句用于指定数据是在一个分组里是如何进行排序的。

    三 分析函数类型

    Oracle有以下类型的分析函数,其中,带有*号的函数可以使用上面的完全语句,包括窗口子句。

    • AVG *
    • COPR *
    • COUNT *
    • COVAR_POP *
    • COVAR_SAMP *
    • CUME_DIST
    • DENSE_RANK
    • FIRST
    • FIRST_VALUE *
    • LAG
    • LAST
    • LAST_VALUE *
    • LEAD
    • LISTAGG
    • MAX *
    • MEDIAN
    • MIN *
    • NTH_VALUE *
    • NTILE
    • PERCENT_RANK
    • PERCENTILE_COUNT
    • PERCENTILE_DISC
    • RANK
    • RATIO_TO_REPORT
    • REGR_(Linear Regression) Functions *
    • ROW_NUMBER
    • STDDEV *
    • STDDEV_POP *
    • STDDEV_SAMP *
    • SUM *
    • VAR_POP *
    • VAR_SAMP *
    • VARIANCE *

    四 分析函数详解

    1 演示数据库版本

    SQL> select * from v$version;
    BANNER
    --------------------------------------------------------------------------------
    Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    PL/SQL Release 11.2.0.4.0 - Production
    CORE 11.2.0.4.0 Production
    TNS for Linux: Version 11.2.0.4.0 - Production
    NLSRTL Version 11.2.0.4.0 - Production

    2 AVG函数

    1)语法结构

    AVG函数用于返回expr的平均值,如果指定DISTINCT,那么只能指定analytic_clause中的query_partition_clause子句,不能指定order_by_clause andwindowing_clause子句。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    deptno,
    sal,
    round(AVG(sal) over(), 2) avg_all_sal,
    round(AVG(sal) over(PARTITION BY deptno), 2) avg_dept_sal,
    round(AVG(sal) over(PARTITION BY deptno ORDER BY empno
    rows BETWEEN 1 preceding AND 1 following),2) avg_sal1,
    round(AVG(sal) over(PARTITION BY deptno ORDER BY empno
    rows BETWEEN CURRENT ROW AND 1 following),2) avg_sal2
    FROM emp;

     3 COUNT

    1)语法结构

    COUNT返回查询的行数,如果指定DISTINCT,那么只能指定analytic_clause中的query_partition_clause子句,不能指定order_by_clause andwindowing_clause子句。如果指定expr,COUNT返回expr非空的行数,如果指定*,则返回所有行数,包括重复行和空行。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    deptno,
    sal,
    comm,
    COUNT(1) over() qty1,
    COUNT(*) over() qty2,
    COUNT(comm) over() qty3,
    COUNT(DISTINCT deptno) over() qty4,
    COUNT(1) over(PARTITION BY deptno) qty5
    FROM emp;

    4 RANK、DENSE_RANK、ROW_NUMBER

    1)语法结构

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    --row_number() over(ORDER BY sal) rn1,
    row_number() over(PARTITION BY deptno ORDER BY sal) rn2,
    --rank()over(order by sal) rn3
    rank() over(PARTITION BY deptno ORDER BY sal) r4,
    dense_rank() over(PARTITION BY deptno ORDER BY sal) r5
    FROM emp;

    注:这三个函数主要用于进行排序,ROW_NUMBER函数排序的结果是连续的,而DENSE函数排序会出现跳号,DENSE_RANK函数排序,不会出现跳号。

    5 FIRST_VALUE

    1)语法结构

    FIRST_VALUE用于返回在一个排序结果集中的第一个值。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    first_value(sal) over(PARTITION BY deptno ORDER BY sal) sal,
    first_value(sal) over(PARTITION BY deptno ORDER BY sal DESC) sal2
    FROM emp;

    6 LAST_VALUE

    1)语法结构

    对于该函数,如果忽略了analytic_clause子句中的windowing_clause子句,默认是使用RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ,使用默认值有时可能返回不是预期的结果,因为LAST VALUE是窗口中的最后一个值,它不是固定的,而是随着当前行的改变而改变。为了得到与其的结果,可以使用RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING窗口,也可以使用RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING窗口。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    last_value(sal) over(PARTITION BY deptno ORDER BY sal) sal1,
    last_value(sal) over(PARTITION BY deptno ORDER BY sal RANGE BETWEEN unbounded preceding AND CURRENT ROW) sal2,
    last_value(sal) over(PARTITION BY deptno ORDER BY sal RANGE BETWEEN unbounded preceding AND unbounded following) sal3,
    last_value(sal) over(PARTITION BY deptno ORDER BY sal RANGE BETWEEN CURRENT ROW AND unbounded following) sal4,
    last_value(sal) over(PARTITION BY deptno ORDER BY sal DESC RANGE BETWEEN unbounded preceding AND unbounded following) sal5,
    last_value(sal) over(PARTITION BY deptno ORDER BY sal rows BETWEEN unbounded preceding AND unbounded following) sal6
    FROM emp;

    7 LAG

    1)语法结构

    该函数提供了在不使用自连接的情况下同时访问表的多行的能力,即将数据行根据偏移量靠后,offset参数指定偏移量,默认值为1,default参数指定超过窗口边界的默认值,没有指定,则为NULL。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    lag(sal) over(PARTITION BY deptno ORDER BY sal) sal1,
    lag(sal, 1) over(PARTITION BY deptno ORDER BY sal) sal2,
    lag(sal, 2, 0) over(PARTITION BY deptno ORDER BY sal) sal3
    FROM emp;

    8 LEAD

    1)语法结构

    该函数和LAG函数功能相反,主要用于将行数据提前。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    lead(sal) over(PARTITION BY deptno ORDER BY sal) sal1,
    lead(sal, 1) over(PARTITION BY deptno ORDER BY sal) sal2,
    lead(sal, 2, 0) over(PARTITION BY deptno ORDER BY sal) sal3
    FROM emp;

    9 LISTAGG

    1)语法结构

    该函数用于在分组内对数据进行排序,然后将对应的值进行拼接,参数delimilter用于指定拼接符。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    listagg(ename, ',') within GROUP(ORDER BY empno) over(PARTITION BY deptno) name1
    FROM emp;

    思考:如果拼接的列数据类型为varchar2,则有无长度限制,如果超过了该怎么处理?

    SQL> SELECT deptno,
    dbms_lob.substr(substr(rtrim(xmlcast(xmlagg(xmlelement(e,
    ename || ',')
    ORDER BY empno) AS CLOB),
    ','),
    1,
    100)) NAME
    FROM emp
    GROUP BY deptno;

    10 MAX、MIN、SUM

    1)语法结构

    这三个函数主要用于在分组内求最大值、最小值以及求和。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    MAX(sal) over() sal1,
    MAX(sal) over(PARTITION BY deptno) sal2,
    MAX(sal) over(PARTITION BY deptno ORDER BY empno rows BETWEEN unbounded preceding AND 1 following) sal3,
    MIN(sal) over() sal4,
    MIN(sal) over(PARTITION BY deptno) sal5,
    MIN(sal) over(PARTITION BY deptno ORDER BY empno rows BETWEEN unbounded preceding AND 1 following) sal6,
    SUM(sal) over() sal7,
    SUM(sal) over(PARTITION BY deptno) sal8,
    SUM(sal) over(PARTITION BY deptno ORDER BY empno rows BETWEEN unbounded preceding AND 1 following) sal9
    FROM emp;

    11 CUME_DIST

    1)语法结构

    该函数用于计算一个值在一组值中的累积分布,返回的值的范围是0到1。计算逻辑为:在一组值中某一个值的相对位置,即对于某一行R,总行数为N,值为R/N。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    cume_dist() over(ORDER BY sal) p1,
    cume_dist() over(PARTITION BY deptno ORDER BY sal) p2
    FROM emp
    ORDER BY deptno, sal;

    12 PERCENT_RANK

    1)语法结构

    该函数和CUME_DIST函数类似,返回值的范围是0到1,使用该函数的任何集合的第一行是0。计算逻辑为:对于某一行R,总行数为N,值为(R-1)/(N-1)。

    2)示例

    SQL> SELECT empno,
    ename,
    job,
    mgr,
    hiredate,
    sal,
    deptno,
    percent_rank() over(ORDER BY sal) p1,
    percent_rank() over(PARTITION BY deptno ORDER BY sal) p2
    FROM emp
    ORDER BY deptno, sal;

  • 相关阅读:
    luogu P3376 【模板】网络最大流
    cogs 774. [USACO Open09] 捉迷藏
    1002. A+B for Polynomials (25) (浮点数判0)
    1001. A+B Format (20) (%0nd)
    7-28 搜索树判断(25 分)
    7-27 家谱处理(30 分)
    7-26 Windows消息队列(25 分)(堆排序)
    7-25 朋友圈(25 分)(并查集)
    7-24 树种统计(25 分)(二叉排序的应用)
    7-23 还原二叉树(25 分)
  • 原文地址:https://www.cnblogs.com/alen-liu-sz/p/12975601.html
Copyright © 2011-2022 走看看