oracle的分析函数over(Partition by...)

Sql代码

over(Partition by...) 一个超级牛皮的ORACLE特有函数。

最近工作中才接触到这个功能强大而灵活的函数。

oracle的分析函数over 及开窗函数

一:分析函数over

Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是

对于每个组返回多行,而聚合函数对于每个组只返回一行。

下面通过几个例子来说明其应用。

  1 1:统计某商店的营业额。
  2      date       sale
  3      1           20
  4      2           15
  5      3           14
  6      4           18
  7      5           30
  8     规则:按天统计:每天都统计前面几天的总额
  9     得到的结果:
 10     DATE   SALE       SUM
 11     ----- -------- ------
 12     1      20        20           --1天
 13     2      15        35           --1天+2天
 14     3      14        49           --1天+2天+3天
 15     4      18        67            .
 16     5      30        97            .
 17
 18 2:统计各班成绩第一名的同学信息
 19     NAME   CLASS S
 20     ----- ----- ----------------------
 21     fda    1      80
 22     ffd    1      78
 23     dss    1      95
 24     cfe    2      74
 25     gds    2      92
 26     gf     3      99
 27     ddd    3      99
 28     adf    3      45
 29     asdf   3      55
 30     3dd    3      78
 31
 32     通过:
 33     --
 34     select * from
 35     (
 36     select name,class,s,rank()over(partition by class order by s desc) mm from t2
 37     )
 38     where mm=1
 39     --
 40     得到结果:
 41     NAME   CLASS S                       MM
 42     ----- ----- ---------------------- ----------------------
 43     dss    1      95                      1
 44     gds    2      92                      1
 45     gf     3      99                      1
 46     ddd    3      99                      1
 47
 48     注意:
 49     1.在求第一名成绩的时候,不能用row_number(),因为如果同班有两个并列第一,row_number()只返回一个结果
 50     2.rank()和dense_rank()的区别是:
 51       --rank()是跳跃排序,有两个第二名时接下来就是第四名
 52       --dense_rank()l是连续排序,有两个第二名时仍然跟着第三名
 53
 54
 55 3.分类统计 (并显示信息)
 56     A   B   C
 57     -- -- ----------------------
 58     m   a   2
 59     n   a   3
 60     m   a   2
 61     n   b   2
 62     n   b   1
 63     x   b   3
 64     x   b   2
 65     x   b   4
 66     h   b   3
 67    select a,c,sum(c)over(partition by a) from t2
 68    得到结果:
 69    A   B   C        SUM(C)OVER(PARTITIONBYA)
 70    -- -- ------- ------------------------
 71    h   b   3        3
 72    m   a   2        4
 73    m   a   2        4
 74    n   a   3        6
 75    n   b   2        6
 76    n   b   1        6
 77    x   b   3        9
 78    x   b   2        9
 79    x   b   4        9
 80
 81    如果用sum,group by 则只能得到
 82    A   SUM(C)
 83    -- ----------------------
 84    h   3
 85    m   4
 86    n   6
 87    x   9
 88    无法得到B列值
 89
 90 =====
 91 select * from test
 92
 93 数据:
 94 A B C
 95 1 1 1
 96 1 2 2
 97 1 3 3
 98 2 2 5
 99 3 4 6
100
101
102 ---将B栏位值相同的对应的C 栏位值加总
103 select a,b,c, SUM(C) OVER (PARTITION BY B) C_Sum
104 from test
105
106 A B C C_SUM
107 1 1 1 1
108 1 2 2 7
109 2 2 5 7
110 1 3 3 3
111 3 4 6 6
112
113 ---如果不需要已某个栏位的值分割,那就要用 null
114
115 eg: 就是将C的栏位值summary 放在每行后面
116
117 select a,b,c, SUM(C) OVER (PARTITION BY null) C_Sum
118 from test
119
120 A B C C_SUM
121 1 1 1 17
122 1 2 2 17
123 1 3 3 17
124 2 2 5 17
125 3 4 6 17
126
127 求个人工资占部门工资的百分比
128
129 SQL> select * from salary;
130
131 NAME DEPT SAL
132 ---------- ---- -----
133 a 10 2000
134 b 10 3000
135 c 10 5000
136 d 20 4000
137
138 SQL> select name,dept,sal,sal*100/sum(sal) over(partition by dept) percent from salary;
139
140 NAME DEPT SAL PERCENT
141 ---------- ---- ----- ----------
142 a 10 2000 20
143 b 10 3000 30
144 c 10 5000 50
145 d 20 4000 100
146
147 二:开窗函数
148       开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:
149 1:
150    over(order by salary) 按照salary排序进行累计,order by是个默认的开窗函数
151    over(partition by deptno)按照部门分区
152 2:
153   over(order by salary range between 5 preceding and 5 following)
154    每行对应的数据窗口是之前行幅度值不超过5,之后行幅度值不超过5
155    例如:对于以下列
156      aa
157      1
158      2
159      2
160      2
161      3
162      4
163      5
164      6
165      7
166      9
167
168    sum(aa)over(order by aa range between 2 preceding and 2 following)
169    得出的结果是
170             AA                       SUM
171             ---------------------- -------------------------------------------------------
172             1                       10
173             2                       14
174             2                       14
175             2                       14
176             3                       18
177             4                       18
178             5                       22
179             6                       18
180             7                       22
181             9                       9
182
183    就是说,对于aa=5的一行 ,sum为   5-1<=aa<=5+2 的和
184    对于aa=2来说 ,sum=1+2+2+2+3+4=14     ;
185    又如 对于aa=9 ,9-1<=aa<=9+2 只有9一个数,所以sum=9    ;
186
187 3:其它:
188      over(order by salary rows between 2 preceding and 4 following)
189           每行对应的数据窗口是之前2行,之后4行
190 4:下面三条语句等效:
191      over(order by salary rows between unbounded preceding and unbounded following)
192           每行对应的数据窗口是从第一行到最后一行,等效:
193      over(order by salary range between unbounded preceding and unbounded following)
194            等效
195      over(partition by null)
196
197 常用的分析函数如下所列:
198
199 row_number() over(partition by ... order by ...)
200 rank() over(partition by ... order by ...)
201 dense_rank() over(partition by ... order by ...)
202 count() over(partition by ... order by ...)
203 max() over(partition by ... order by ...)
204 min() over(partition by ... order by ...)
205 sum() over(partition by ... order by ...)
206 avg() over(partition by ... order by ...)
207 first_value() over(partition by ... order by ...)
208 last_value() over(partition by ... order by ...)
209 lag() over(partition by ... order by ...)
210 lead() over(partition by ... order by ...)
211
212 示例
213 SQL> select type,qty from test;
214
215 TYPE QTY
216 ---------- ----------
217 1 6
218 2 9
219
220  SQL> select type,qty,to_char(row_number() over(partition by type order by qty))||'/'||to_char(count(*) over(partition by type)) as cnt2 from test;
221
222 TYPE QTY CNT2
223 ---------- ---------- ------------
224 3 1/2
225 1 6 2/2
226 2 5 1/3
227 7 2/3
228 2 9 3/3
229
230  SQL> select * from test;
231 ---------- -------------------------------------------------
232 1 11111
233 2 22222
234 3 33333
235 4 44444
236
237 SQL> select t.id,mc,to_char(b.rn)||'/'||t.id)e
238 2 from test t,
239  (select rownum rn from (select max(to_number(id)) mid from test) connect by rownum <=mid ))L
240 4 where b.rn<=to_number(t.id)
241 order by id
242
243 ID MC TO_CHAR(B.RN)||'/'||T.ID
244 --------- -------------------------------------------------- ---------------------------------------------------
245 1 11111 1/1
246 2 22222 1/2
247 2 22222 2/2
248 3 33333 1/3
249 3 33333 2/3
250 3 33333 3/3
251  44444 1/4 44444 2/4
252 4 44444 3/4CNOUG4 44444 4/4
253
254 10 rows selected
255
256 *******************************************************************

2,rank over 说明

排序:

---rank()over(order by 列名 排序)的结果是不连续的,如果有4个人,其中有3个是并列第1名,那么最后的排序结果结果如:1 1 1 4
select scoreid, studentid,COURSENAME,totalexamscore ,
rank()over(order by TOTALEXAMSCORE desc)orderbyNum
from SCORECOURSE a ,COURSESCORE b
where a.SCORECOURSEID = b.SCORECOURSEID

---dense_rank()over(order by 列名 排序)的结果是连续的,如果有4个人,其中有3个是并列第1名, 那么最后的排序结果如:1 1 1 2
select scoreid, studentid,COURSENAME,totalexamscore ,
dense_rank()over(order by TOTALEXAMSCORE desc)orderbyNum
from SCORECOURSE a ,COURSESCORE b
where a.SCORECOURSEID = b.SCORECOURSEID

----rank () OVER (PARTITION BY 列名 ORDER BY 列名 排序)使用分区方式获取每门课程的最高分
SELECT *
  FROM (SELECT scoreid, studentid, coursename, TOTALEXAMSCORE,
               rank () OVER (PARTITION BY coursename ORDER BY TOTALEXAMSCORE DESC)orderbynum
          FROM scorecourse a, coursescore b
         WHERE a.scorecourseid = b.scorecourseid and studentID = 'xxxxx')
 WHERE orderbynum < 2

-----使用over实现成绩求和
-----SUM (totalexamscore) OVER (ORDER BY studentid) sum1  实现的是连续求和,如第一个学生的总评成绩是30,则sum1就展示为30,到第二个学生成绩出现的时候,则会依次累加
-----SUM (totalexamscore) OVER () sum2 就相当于是单纯的求和,和直接使用sum是一致的
SELECT scoreid, studentid, totalexamscore,
       SUM (totalexamscore) OVER (ORDER BY studentid) sum1,
       SUM (totalexamscore) OVER () sum2
  FROM coursescore
注:这个案例想了很久也没想到很直观的描述,还请大家亲自去测试一下吧!!

语法:
rank() over (order by 排序字段 顺序)
rank() over (partition by 分组字段 order by 排序字段 顺序)

1.顺序:asc|desc  名次与业务相关:
  示例:求优秀学员,成绩:降序  迟到次数:升序
2.分区字段:根据什么字段进行分区。

问题:分区与分组有什么区别?
•分区只是将原始数据进行名次排列(记录数不变),
•分组是对原始数据进行聚合统计(记录数变少,每组返回一条)。

注意:使用rank()over(order by 排序字段 顺序)排序的时候,空值是最大的
(如果排序字段为null,可能造成在排序时将null字段排在最前面,影响排序的正确性。
所以建议将dense_rank()over(order by 列名 排序)改为dense_rank()over(order by 列名 排序 nulls last)
这样只要排序字段为null,就会放在最后,而不会影响排序结果).

转载于:https://www.cnblogs.com/strivers/p/8351306.html

Oracle分析函数简析相关推荐

  1. oracle上浮下浮分析函数_Oracle分析函数简析

    oracle的分析函数over(Partition by...) Sql代码 over(Partition by...) 一个超级牛皮的ORACLE特有函数. 最近工作中才接触到这个功能强大而灵活的函 ...

  2. oracle Swap_join_inputs简析

    此hint仅针对hash_join有效,强行交换驱动关系;目标表为 原hash连接的被驱动表,适合的场景: 1.多表的hash内连接(大于2个以上) 2.多表的hash外连接(大于等于2个以上) 场景 ...

  3. php mysql 命令行模式_MySQL_MYSQL导入导出sql文件简析,一.MYSQL的命令行模式的设置- phpStudy...

    MYSQL导入导出sql文件简析 一.MYSQL的命令行模式的设置 桌面->我的电脑->属性->环境变量->新建-> PATH=":path\mysql\bin ...

  4. 简析金融IT行业发展前景

    金融IT行业是金融和IT的交叉行业,这个行业尚没有明确的定义.本文简析了金融IT行业的特点,探讨了金融IT行业中常见的职位并对金融IT行业的就业前景提出了自己的看法. 一.定义 1.金融和金融行业的定 ...

  5. Android V1及V2签名原理简析

    Android为了保证系统及应用的安全性,在安装APK的时候需要校验包的完整性,同时,对于覆盖安装的场景还要校验新旧是否匹配,这两者都是通过Android签名机制来进行保证的,本文就简单看下Andro ...

  6. Mysql锁机制及原理简析

    Mysql锁机制及原理简析 一.前言 1.什么是锁? 锁是计算机协调多个进程或线程并发访问某一资源的机制. 锁保证数据并发访问的一致性.有效性: 锁冲突也是影响数据库并发访问性能的一个重要因素. 锁是 ...

  7. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  8. 简析平衡树(三)——浅谈Splay

    前言 原本以为\(Treap\)已经很难了,学习了\(Splay\),我才知道,没有最难,只有更难.(强烈建议先去学一学\(Treap\)再来看这篇博客) 简介 \(Splay\)是平衡树中的一种,除 ...

  9. 基于libmad库的MP3解码简析

    基于libmad库的MP3解码简析  MAD (libmad)是一个开源的高精度 MPEG 音频解码库,支持 MPEG-1(Layer I, Layer II 和 LayerIII(也就是 MP3). ...

  10. 简析 .NET Core 构成体系

    简析 .NET Core 构成体系 Roslyn 编译器 RyuJIT 编译器 CoreCLR & CoreRT CoreFX(.NET Core Libraries) .NET Core 代 ...

最新文章

  1. 怎样查看一个端口有无开启
  2. Windows中几个内存相当的指标
  3. BurpSuite插件 -- FastjsonScan(反序列化检测)
  4. AI应用开发基础傻瓜书系列3-损失函数
  5. 作者:杨琪,数据堂(北京)科技股份有限公司企业发展部副总监。
  6. 在ecshop商品详情页显示供货商
  7. android各版本市场占有率报告,你用的是哪个版本 Android系统报告:果冻豆市占率升至62%...
  8. iphone safari不支持position fixed的解决办法
  9. 表单和ajax中的post请求后台获取数据方法
  10. Git学代码之学会运行别人的代码
  11. 【ABMDRNet2021】 Adaptive-weighted Bi-directional Modality Difference Reduction Network for RGB-T Sema
  12. TCP端口映射与转发软件(TCP Mapping)简介
  13. Unity Shader - 伪次表面散射模拟
  14. 三肽Gly-Cys-Gly、88440-55-5
  15. GotW#63 狂乱的代码
  16. Jquery中AJAX参数详细列表
  17. 接上篇《旋转矩阵的作用:世界坐标变换;求解局部坐标系下的局部坐标》,理解欧拉角:内旋;外旋;万向节死锁
  18. 2455. 可被三整除的偶数的平均值
  19. Ubuntu 20.04 live server版安装(详细版)
  20. react native 啧啧啧

热门文章

  1. Hibernate:1对1关系总结。
  2. logrotate日志管理工具
  3. 斐波那契数列n项的值。(递归和非递归算法Golang实现)
  4. 深入Node.js的模块机制
  5. Spring mvc框架 controller间跳转 ,重定向 ,传参
  6. android动画的实现过程
  7. OpenStack最新版本Folsom架构解析(转)
  8. 关于 FROM tableA,tableB 和 tableA LEFT JOIN tableB on 的区别
  9. Android 中进程的级别以及 Service 的优先级
  10. legend---六、php脚本变量的生命周期是怎样的