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>, <default>) 访问之前的行,OFFSET是缺省为1 的正数,表示相对行数,DEFAULT是当超出选定窗范围时的返回值(如第一行不存在之前行)
11 LEAD(expr, <offset>, <default>) 访问之后的行,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(表达式值)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 分析函数,也称为窗口函数,通常被认为仅对数据仓库SQL有用。使用分析函数的查询,基于对数据行的分组来计算总量值。与...
    猫猫_tomluo阅读 3,207评论 3 18
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 七.Excel统计函数 1.计数和频率 COUNT返回提供的一组单元格或值中的数值数 COUNTA返回所提供的一组...
    浮浮尘尘阅读 3,507评论 0 46
  • 按照用途分类出以下统计函数: AVEDEV 用途:返回一组数据与其平均值的绝对偏差的平均值,该函数可以评测数据(例...
    四方院祭司阅读 2,745评论 0 3
  • 2017/3/14 RDBMS:关系型数据库管理系统 关系模型独立于语言 SQL有几种不同类型的语言:数据定义语言...
    ancherl阅读 1,536评论 0 6