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
如果用
sum
,
group
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
1
2
2
2
3
4
5
6
7
9
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
*******************************************************************
|
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;
|