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

oracle的分析函数over 及开窗函数的更多相关文章

  1. 超级牛皮的oracle的分析函数over(Partition by...) 及开窗函数 (转)

    http://zonghl8006.blog.163.com/blog/static/4528311520083995931317/ over(Partition by...) 一个超级牛皮的ORAC ...

  2. 超级牛皮的oracle的分析函数over(Partition by...) 及开窗函数

    over(Partition by...) 一个超级牛皮的ORACLE特有函数. 天天都用ORACLE,用了快2年了.最近才接触到这个功能强大而灵活的函数.真实惭愧啊! oracle的分析函数over ...

  3. oracle的分析函数over(Partition by...) 及开窗函数

        over(Partition by...) 一个超级牛皮的ORACLE特有函数. oracle的分析函数over 及开窗函数一:分析函数overOracle从8.1.6开始提供分析函数,分析函 ...

  4. [转]Oracle 语法之 OVER (PARTITION BY ..) 及开窗函数

    oracle的分析函数over 及开窗函数 一:分析函数Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是 对于每个组返回多行,而聚合函数对于每个组 ...

  5. Oracle 开窗函数--转

    oracle的分析函数over 及开窗函数 转自:http://zonghl8006.blog.163.com/blog/static/4528311520083995931317/一:分析函数ove ...

  6. oracle分析函数技术详解(配上开窗函数over())

    一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...

  7. oracle 分析函数和开窗函数

    最近遇到一个需求,将查询出的数据按照地区分组,随机取出每个区域的2条数据,这里用到了oracle的分析和开窗函数: 最终写出的sql如下: select * from (select region,r ...

  8. Oracle开窗函数笔记及应用场景

    介绍Oracle的开窗函数之前先介绍一下分析函数,因为开窗函数也属于分析函数 分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行. 上面是 ...

  9. (MariaDB)开窗函数用法

    本文目录: 1.1 窗口和开窗函数简介 1.2 OVER()语法和执行位置 1.3 row_number()对分区排名 1.4 rank()和dense_rank() 1.5 percent_rank ...

随机推荐

  1. 图片上传预览 (URL.createObjectURL)

    知识预备:1. URL.createObjectURL() 静态方法会创建一个 DOMString,它的 URL 表示参数中的对象.这个 URL 的生命周期和创建它的窗口中的 document 绑定. ...

  2. scala 宏

    Scala开发团队正在将实验版宏指令加入到即将发行的2.10版中.Scala宏指令提供了编译时元编程的高级形式.Scala宏网站描述道: “宏指令显著简化了代码分析和代码生成,这使得它们成为处理大量现 ...

  3. IT技术学习指导之Linux系统入门的4个阶段(纯干货带图)

    IT技术学习指导之Linux系统入门的4个阶段(纯干货带图) 全世界60%的人都在使用Linux.几乎没有人没有受到Linux系统的"恩惠",我们享受的大量服务(包括网页服务.聊天 ...

  4. bzoj2006: [NOI2010]超级钢琴

    题意:给一个序列(n<=500000),要求选定k个不同区间,使得区间长度在L,R之间,并使得k个区间和之和最大,输出这个最大值. 刚拿到题的时候想的是,对于每个点,如果以它开头,那么之后的L- ...

  5. Redis学习笔记~实现消息队列比MSMQ更方便

    什么是队列:简单的说就是数据存储到一个空间里(可以是内存,也可以是物理文件),先存储的数据对象,先被取出来,这与堆栈正好相反,消息队列也是这样,将可能出现高并发的数据进行队列存储,并按着入队的顺序依次 ...

  6. GDB配置与.gdbinit的编写

    GDB配置与.gdbinit的编写 当 GDB(即 GNU Project Debugger)启动时,它在当前用户的主目录中寻找一个名为 .gdbinit 的文件:如果该文件存在,则 GDB 就执行该 ...

  7. 用Runtime.getRuntime().exec()需要注意的地方

    有时候我们可能需要调用系统外部的某个程序,此时就可以用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序. 此方法返回一个java.lang.Proce ...

  8. php学习

    一.session使用: 1.所有内容页——最前面(<html>标签以前)添加以下代码: <?php if(!isset($_session)){ session_start(); ...

  9. Ubuntu Install Java

    http://linuxpilot.com/ubuntu-java class HelloWorld{public static void main(String[]arg){System.out.p ...

  10. IE6不支持min-height或max-width等完美解决方法

    又是IE6!!!坑人的IE6,不支持min-height,但是实际操作中,这个属性是非常需要的.那IE6下面怎么实现呢?请看geniusalien提供的完美解决方案:(geniusalien温馨提示: ...