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

转:http://www.2cto.com/database/201310/249722.html

一:分析函数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;

时间: 2024-10-15 09:11:25

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

Oacle 开窗函数 分析函数

http://zonghl8006.blog.163.com/blog/static/4528311520083995931317/ over(Partition by...) 一个超级牛皮的ORACLE特有函数. 天天都用ORACLE,用了快2年了.最近才接触到这个功能强大而灵活的函数.真实惭愧啊! oracle的分析函数over 及开窗函数一:分析函数overOracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对

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

oracle的分析函数over 及开窗函数 一:分析函数Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是 对于每个组返回多行,而聚合函数对于每个组只返回一行. 下面通过几个例子来说明其应用. 1:统计某商店的营业额. date       sale 1           20 2           15 3           14 4           18 5           30 规则:按天统计:每天都统计前面几天的总额 se

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

Sql代码 over(Partition by...) 一个超级牛皮的ORACLE特有函数. 最近工作中才接触到这个功能强大而灵活的函数. 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

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

一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值. 分析函数和聚合函数的不同之处是什么?普通的聚合函数用group by分组,每个分组返回一个统计值,而分析函数采用partition by分组,并且每组每行都可以返回一个统计值. 分析函数的形式分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(or

分析函数之开窗函数over

一.分析函数 -- Oracle从8.1.6开始提供分析函数,专门用于解决复杂报表统计需求的功能强大的函数, -- 它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值.分析函数用于计算基于组的某种聚合值. -- 它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行.普通的聚合函数用group by分组, -- 每个分组返回一个统计值:而分析函数采用partition by分组,并且每组每行都可以返回一个统计值. -- 1.分析函数的形

oracle 之分析函数 over (partition by ...order by ...)

一:分析函数overOracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行. 1.分析函数和聚合函数的不同之处: 分析函数和聚合函数很多是同名的,意思也一样,只是聚合函数用group by分组,每个分组返回一个统计值,而分析函数采用partition by分组,并且每组每行都可以返回一个统计值.简单的说就是聚合函数返回统计结果,分析函数返回明细加统计结果. (一).分析函数语法: FUNCTION_

SQL开窗函数

开窗函数:在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成.为了解决这些问题,在 2003 年 ISO SQL 标准加入了开窗函数,开窗函数的使用使得这些经典的难题可以被轻松的解决.目前在 MSSQLServer.Oracle.DB2 等主流数据库中都提供了对开窗函数的支持,不过非常遗憾的是 MYSQL 暂时还未对开窗函数给予支持. 开窗函数简介:与聚合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值

深入浅出谈开窗函数(一)

      在开窗函数出现之前存在着非常多用 SQL 语句非常难解决的问题,非常多都要通过复杂的相关子查询或者存储过程来完毕.为了解决这些问题,在2003年ISO  SQL标准增加了开窗函数,开窗函数的使用使得这些经典的难题能够被轻松的解决.眼下在 MSSQLServer.Oracle.DB2 等主流数据库中都提供了对开窗函数的支持,只是非常遗憾的是 MYSQL 临时还未对开窗函数给予支持.  为了更加清楚地理解,我们来建表并进行相关的查询(截图为MSSQLServer中的结果)        

oracle下的OVER(PARTITION BY)函数介绍

转自:http://www.cnblogs.com/lanzi/archive/2010/10/26/1861338.html OVER(PARTITION BY)函数介绍 开窗函数               Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行. 开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:1:over后的写法: