Oracle分析函数用法详解

OVER(PARTITION BY)开窗函数用法

开窗函数,Oracle从8.1.6开始提供开窗函数,开窗函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:
对于每个组返回多行,而聚合函数对于每个组只返回一行。
开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化。

开窗的窗口范围

-- 窗口范围为当前行数据幅度减3加3后的范围内的.
/*SELECT 
   T1.STUDENT_NAME
   ,T1.CLASS_NAME
   ,T1.COURSE_SCORE
   ,SUM(T1.COURSE_SCORE) OVER(ORDER BY COURSE_SCORE RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWING) SUM_SCORE
  FROM V_RPT_COURSE_STUDENT T1
WHERE T1.EXAM_COURSE_ID = '730F9DDBD98543F2B595D3898F86AC67'
AND T1.EXAM_ID = '8793AF04C83F468A89BE12229257D65A'
AND T1.CLASS_ID = 'B3469FDB0F674523AACF1C3F2E015A88'*/

/*1 高蓉蓉 1班  76  155   76,79
  2 雷蕾   1班  79  237   76,79,82
  3 杨正坤 1班  82  331   79,82,85,85
  4 李永承 1班  85  252   82,85,85
  5 敬金凤 1班  85  252   82,85,85  */

窗口范围为当前行前后各移动1,0行

/*SELECT 
   T1.STUDENT_NAME
   ,T1.CLASS_NAME
   ,T1.COURSE_SCORE
   ,SUM(T1.COURSE_SCORE) OVER(ORDER BY COURSE_SCORE ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) SUM_SCORE
  FROM V_RPT_COURSE_STUDENT T1
WHERE T1.EXAM_COURSE_ID = '730F9DDBD98543F2B595D3898F86AC67'
AND T1.EXAM_ID = '8793AF04C83F468A89BE12229257D65A'
AND T1.CLASS_ID = 'B3469FDB0F674523AACF1C3F2E015A88'
*/

/*1 高蓉蓉 1班  76  76   76
  2 雷蕾  1班  79  155   76,79
  3 杨正坤 1班  82  161  79,82
  4 李永承 1班  85  167  82,85
  5 敬金凤 1班  85  170  85,85 */

窗口不做限制

/*SELECT 
   T1.STUDENT_NAME
   ,T1.CLASS_NAME
   ,T1.COURSE_SCORE
   ,SUM(T1.COURSE_SCORE) OVER(ORDER BY COURSE_SCORE RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) SUM_SCORE1
   ,SUM(T1.COURSE_SCORE) OVER(ORDER BY COURSE_SCORE ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) SUM_SCORE2
   ,SUM(T1.COURSE_SCORE) OVER() SUM_SCORE3
  FROM V_RPT_COURSE_STUDENT T1
WHERE T1.EXAM_COURSE_ID = '730F9DDBD98543F2B595D3898F86AC67'
AND T1.EXAM_ID = '8793AF04C83F468A89BE12229257D65A'
AND T1.CLASS_ID = 'B3469FDB0F674523AACF1C3F2E015A88'*/


/*1 高蓉蓉 1班  76  407 407 407
  2 雷蕾  1班   79  407    407 407
  3 杨正坤 1班  82  407 407 407
  4 李永承 1班  85  407 407 407
  5 敬金凤 1班  85  407 407 407*/

与OVER函数结合的几个函数介绍

/*与OVER函数结合的几个函数介绍
 ROW_NUMBER() OVER()、RANK() OVER()和DENSE_RANK() OVER()函数的使用
 
 RANK        跳跃排序
 DENSE_RANK  连续排序
 
 */
 
/*SELECT T.*
     ,RANK() OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE DESC) SCORE_RANK
     ,ROW_NUMBER() OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE DESC) SCORE_ROW_NUMBER
     ,DENSE_RANK() OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE DESC) SCORE_DENSE_RANK
     ,SUM(T.COURSE_SCORE) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE DESC) SCORE_SUM
 FROM ( 
 SELECT 
   T1.STUDENT_NAME
   ,T1.CLASS_NAME
   ,T1.COURSE_SCORE
  FROM V_RPT_COURSE_STUDENT T1
WHERE T1.EXAM_COURSE_ID = '730F9DDBD98543F2B595D3898F86AC67'
AND T1.EXAM_ID = '8793AF04C83F468A89BE12229257D65A'
AND T1.CLASS_ID = 'B3469FDB0F674523AACF1C3F2E015A88' ) T
*/

/*1 敬金凤 1班  85  1   1   1   170
 2  李永承 1班  85  1   2   1   170
 3  杨正坤 1班  82  3   3   2   252
 4  雷蕾   1班  79  4  4   3   331
 5  高蓉蓉 1班  76  5   5   4   407*/
 -- 加上IGNORE NULLS后,如果第一条是判断的那个字段是空的,则默认取下一条
 -- FIRST_VALUE和LAST_VALUE常用在计算排过序的结果集中的最大值和最小值。
 
 SELECT T.*
     ,FIRST_VALUE(T.COURSE_SCORE) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE) LOW_SCORE1
     ,FIRST_VALUE(T.COURSE_SCORE IGNORE NULLS) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE) LOW_SCORE2
     ,LAST_VALUE(T.COURSE_SCORE) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE 
                                 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) HIGH_SCORE1
     ,LAST_VALUE(T.COURSE_SCORE) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE) HIGH_SCORE2

                                 
    ,MIN(T.COURSE_SCORE) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE) MIN_SCORE1                                 
    ,MAX(T.COURSE_SCORE) OVER(PARTITION BY T.CLASS_NAME ORDER BY T.COURSE_SCORE) MAX_SCORE1
    
    ,MIN(T.COURSE_SCORE) OVER() MIN_SCORE2                                 
    ,MAX(T.COURSE_SCORE) OVER() MAX_SCORE2
 FROM ( 
 SELECT 
   T1.STUDENT_NAME
   ,T1.CLASS_NAME
   ,T1.COURSE_SCORE
  FROM V_RPT_COURSE_STUDENT T1
WHERE T1.EXAM_COURSE_ID = '730F9DDBD98543F2B595D3898F86AC67'
AND T1.EXAM_ID = '8793AF04C83F468A89BE12229257D65A'
AND T1.CLASS_ID = 'B3469FDB0F674523AACF1C3F2E015A88' ) T


/*1 高蓉蓉 1班  76  76  76  85  76  76  76  76  85
 2  雷蕾  1班  79  76  76  85  79  76  79  76  85
 3  杨正坤 1班  82  76  76  85  82  76  82  76  85
 4  李永承 1班  85  76  76  85  85  76  85  76  85
 5  敬金凤 1班  85  76  76  85  85  76  85  76  85*/

LAG() OVER()函数用法(取出前N行数据)

WITH T AS 
(SELECT 1 ID ,'A' NAME FROM DUAL
 UNION
 SELECT 2 ID ,'B' NAME FROM DUAL
 UNION
 SELECT 3 ID ,'C' NAME FROM DUAL
 UNION
 SELECT 4 ID ,'D' NAME FROM DUAL
 UNION
 SELECT 5 ID ,'E' NAME FROM DUAL
) 
SELECT ID,NAME,LAG(ID,1,'') OVER(ORDER BY NAME) AS LAG_ID FROM T;

/*1 A   
  2 B   1
  3 C   2
  4 D   3
  5 E   4
*/

LEAD() OVER()函数用法(取出后N行数据)

WITH T AS 
(SELECT 1 ID,'A' NAME FROM DUAL
 UNION
 SELECT 2 ID,'B' NAME FROM DUAL
 UNION
 SELECT 3 ID,'C' NAME FROM DUAL
 UNION
 SELECT 4 ID,'D' NAME FROM DUAL
 UNION
 SELECT 5 ID,'E' NAME FROM DUAL
) 
SELECT ID,NAME,LEAD(ID,1,'') OVER(ORDER BY NAME) AS LEAD_ID FROM T;


/*1 A   2
  2 B   3
  3 C   4
  4 D   5
  5 E     */

计算总数百分比

--  RATIO_TO_REPORT(A)函数用法 RATIO_TO_REPORT() 括号中就是分子,OVER() 括号中就是分母
-- 计算总数百分比
WITH T AS (SELECT 1 A FROM DUAL
           UNION ALL
          SELECT 1 A FROM DUAL
          UNION  ALL
          SELECT 1 A FROM DUAL
          UNION ALL
          SELECT 2 A FROM DUAL
          UNION ALL 
          SELECT 3 A FROM DUAL
          UNION ALL
          SELECT 4 A FROM DUAL
          UNION ALL
          SELECT 4 A FROM DUAL
          UNION ALL
          SELECT 5 A FROM DUAL
           )
    SELECT A
        , RATIO_TO_REPORT(A) OVER(PARTITION BY A) B FROM T 
    ORDER BY A; 
    
    
/*1 1   0.333333333333333   1/3
  2 1   0.333333333333333   1/3
  3 1   0.333333333333333   1/3
  4 2   1                   1/1
  5 3   1                   1/1
  6 4   0.5                 1/2
  7 4   0.5                 1/2
  8 5   1                   1/1  */ 

分母缺省就是整个占比

WITH T AS (
    SELECT 1 A FROM DUAL
      UNION ALL
    SELECT 1 A FROM DUAL
      UNION  ALL
    SELECT 1 A FROM DUAL
      UNION ALL
    SELECT 2 A FROM DUAL
      UNION ALL 
    SELECT 3 A FROM DUAL
      UNION ALL
    SELECT 4 A FROM DUAL
      UNION ALL
    SELECT 4 A FROM DUAL
      UNION ALL
    SELECT 5 A FROM DUAL
           )
SELECT A, RATIO_TO_REPORT(A) OVER() B FROM T 
ORDER BY A; 

/*
1   1   0.0476190476190476     1/21
2   1   0.0476190476190476     1/21
3   1   0.0476190476190476     1/21
4   2   0.0952380952380952     2/21
5   3   0.142857142857143      3/21
6   4   0.19047619047619       4/21
7   4   0.19047619047619       4/21
8   5   0.238095238095238      5/21
  21 1
*/

分组后的占比

WITH T AS (
  SELECT 1 A FROM DUAL
      UNION ALL
  SELECT 1 A FROM DUAL
      UNION  ALL
  SELECT 1 A FROM DUAL
      UNION ALL
  SELECT 2 A FROM DUAL
      UNION ALL 
  SELECT 3 A FROM DUAL
      UNION ALL
  SELECT 4 A FROM DUAL
      UNION ALL
  SELECT 4 A FROM DUAL
      UNION ALL
  SELECT 5 A FROM DUAL
           )
SELECT A, RATIO_TO_REPORT(A) OVER() B FROM T
GROUP BY A ORDER BY A;

/*
1   1   0.0666666666666667   1/15
2   2   0.133333333333333    2/15
3   3   0.2                  3/15
4   4   0.266666666666667    4/15
5   5   0.333333333333333    5/15
  15 1 

*/

评级函数

用于等级、百分点、n分片等。
PERCENT_RANK 返回某个值相对于一组值的百分比排名
CUME_DIST 返回特定值对于一组值的位置“CUMULATIVE DISTRIBUTION”(累积分布)
反百分比函数
PERCENTILE_CONT 输入一个百分比(该百分比就是按照PERCENT_RANK函数计算的值),返回该百分比位置的平均值
PERCENTILE_DISC 返回一个与输入的分布百分比值相对应的数据值,分布百分比的计算方法见函数CUME_DIST,如果没有正好对应的数据值,就取大于该分布值的下一个值。

SELECT T.*
   ,PERCENT_RANK() OVER (PARTITION BY CLASS_NAME ORDER BY COURSE_SCORE ) PR1
   ,PERCENT_RANK() OVER (ORDER BY COURSE_SCORE ASC ) PR2
   ,CUME_DIST() OVER(PARTITION BY CLASS_NAME ORDER BY COURSE_SCORE ) PR3
   ,PERCENTILE_CONT(0.25) WITHIN GROUP(ORDER BY COURSE_SCORE) OVER(PARTITION BY CLASS_NAME) PERCENTILE_CONT
   ,PERCENTILE_DISC(0.6) WITHIN GROUP(ORDER BY COURSE_SCORE) OVER(PARTITION BY CLASS_NAME) PERCENTILE_DISC

 FROM ( 
 SELECT 
   T1.STUDENT_NAME
   ,T1.CLASS_NAME
   ,T1.COURSE_SCORE
  FROM V_RPT_COURSE_STUDENT T1
WHERE T1.EXAM_COURSE_ID = '730F9DDBD98543F2B595D3898F86AC67'
AND T1.EXAM_ID = '8793AF04C83F468A89BE12229257D65A'
AND T1.CLASS_ID = 'B3469FDB0F674523AACF1C3F2E015A88' ) T

/*1 高蓉蓉 1班  76  0       0        0.2    79  82
  2 雷蕾   1班  79  0.25    0.25     0.4    79  82
  3 杨正坤 1班  82  0.5   0.5      0.6  79  82
  4 李永承 1班  85  0.75    0.75     1    79    82
  5 敬金凤 1班  85  0.75    0.75     1    79    82*/
序号 函数 说明
1 RANK() 返回数据项在分组中的排名,排名相等会在名次中留下空位
2 DENSE_RANK() 返回数据项在分组中的排名,排名相等会在名次中不会留下空位
3 CUME_DIST() 返回特定值对于一组值的位置“cumulative distribution”(累积分布) ,累积分布,即行在组中的相对位置,返回0 ~ 1
4 PERCENT_RANK() 返回某个值相对于一组值的百分比排名,类似CUME_DIST,1/(行的序数 - 1)
5 NTILE() 返回n分片后的值
6 ROW_NUMBER() 为每条记录返回一个数字
7 DENSE_RANK 行的相对排序(与ORDER BY搭配),相同的值具有一样的序数(NULL计为相同),并不留空序数
8 FIRST_VALUE 一个组的第一个值
9 LAST_VALUE 一个组的最后一个值
10 LAG(expr, , ) 访问之前的行,OFFSET是缺省为1 的正数,表示相对行数,DEFAULT是当超出选定窗范围时的返回值(如第一行不存在之前行)
11 LEAD(expr, , ) 访问之后的行,OFFSET是缺省为1 的正数,表示相对行数,DEFAULT是当超出选定窗范围时的返回值(如最后行不存在之前行)
12 STDDEV(expr) 标准差
13 STDDEV_POP(expr) 总体标准差
14 STDDEV_SAMP(expr) 样本标准差
15 VARIANCE(expr) 方差
16 VAR_POP(expr) 总体方差
17 VAR_SAMP(expr) 样本方差
18 COVAR_POP(expr, expr) 总体协方差
19 COVAR_SAMP(expr, expr) 样本协方差
20 RATIO_TO_REPORT(expr) 表达式值 / SUM(表达式值)

你可能感兴趣的:(Oracle分析函数用法详解)