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