Oracle提供了一些功能很强大的分析函数,使用这些函数可以完成可能需要存储过程来实现的需求。
分析函数计算基于一组数据行的聚合值,它们不同于聚合函数的是,它们为每一组返回多行结果。分析函数是除ORDER BY子句之外,在查询语句中最后执行的。所有的join和所有的WHERE ,GROUP BY 和HAVING子句都在分析函数之前执行。所以分析函数只能出现在select或ORDER BY子句中。
下图为11.2版本官方文档中给出的语法示意图:
analytic_function
指定分析函数的名字,后面列出了所有的分析函数
arguments
分析函数可以有0到3个参数。参数可以是任何数值类型或可以隐式转换为数值类型的其他非数值类型。
analytic_clause
用OVER analytic_clause表明函数操作的是一个查询结果集。如果想过滤基于分析函数的查询结果,需要使用嵌套子查询。
query_partition_clause
用PARTITION BY子句来把查询结果集基于一个或多个value_expr分组。如果省略,分析函数把所有行当作一组。
order_by_clause
用order_by_claus指定在一组中数据如何排序。
ASC(default)|DESC
NULLS FIRST(default in DESC)|NULLS LAST(default in ASC)
windowing_clause
部分分析函数允许使用windowing_clause子句。
只有当指定了order_by_clause后才能指定这个子句。
ROWS指定使用物理行的window
RANGE指定使用逻辑偏移的window
下面为所有的分析函数,带*号的函数允许使用windowing_clause:
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions043.htm#i82886" target="_blank">CUME_DIST</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions052.htm#i1064409" target="_blank">DENSE_RANK</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions065.htm#i1000901" target="_blank">FIRST</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions082.htm#i1327527" target="_blank">LAG</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions083.htm#i1000905" target="_blank">LAST</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions086.htm#i83834" target="_blank">LEAD</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions089.htm#CJABDFBD" target="_blank">LISTAGG</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions099.htm#i1279886" target="_blank">MEDIAN</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions115.htm#i85619" target="_blank">NTILE</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions126.htm#i1043951" target="_blank">PERCENT_RANK</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions127.htm#i1000909" target="_blank">PERCENTILE_CONT</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions128.htm#i1000913" target="_blank">PERCENTILE_DISC</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions141.htm#i1269223" target="_blank">RANK</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions142.htm#i85800" target="_blank">RATIO_TO_REPORT</a>
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions156.htm#i86310" target="_blank">ROW_NUMBER</a>
以AVG为例介绍分析函数的使用:
AVG也是一个聚合函数:
<code>scott@TEST></code><code>select</code> <code>avg</code><code>(sal) </code><code>from</code> <code>emp;</code>
<code> </code><code>AVG</code><code>(SAL)</code>
<code>----------</code>
<code>2073.21429</code>
作为分析函数的例子:
eg1:单独使用
<code>scott@TEST></code><code>select</code> <code>deptno,ename,hiredate,sal,</code><code>avg</code><code>(sal) over() </code><code>avg</code> <code>from</code> <code>emp;</code>
<code> </code><code>DEPTNO ENAME HIREDATE SAL </code><code>AVG</code>
<code>---------- ------------------------------ ------------------- ---------- ----------</code>
<code> </code><code>20 SMITH 1980-12-17 00:00:00 800 2073.21429</code>
<code> </code><code>30 ALLEN 1981-02-20 00:00:00 1600 2073.21429</code>
<code> </code><code>30 WARD 1981-02-22 00:00:00 1250 2073.21429</code>
<code> </code><code>20 JONES 1981-04-02 00:00:00 2975 2073.21429</code>
<code> </code><code>30 MARTIN 1981-09-28 00:00:00 1250 2073.21429</code>
<code> </code><code>30 BLAKE 1981-05-01 00:00:00 2850 2073.21429</code>
<code> </code><code>10 CLARK 1981-06-09 00:00:00 2450 2073.21429</code>
<code> </code><code>20 SCOTT 1987-04-19 00:00:00 3000 2073.21429</code>
<code> </code><code>10 KING 1981-11-17 00:00:00 5000 2073.21429</code>
<code> </code><code>30 TURNER 1981-09-08 00:00:00 1500 2073.21429</code>
<code> </code><code>20 ADAMS 1987-05-23 00:00:00 1100 2073.21429</code>
<code> </code><code>30 JAMES 1981-12-03 00:00:00 950 2073.21429</code>
<code> </code><code>20 FORD 1981-12-03 00:00:00 3000 2073.21429</code>
<code> </code><code>10 MILLER 1982-01-23 00:00:00 1300 2073.21429</code>
从输出可以看出函数计算出了整体的平均值,并输出到每一行
eg2:使用query_partition_clause
<code>scott@TEST></code><code>select</code> <code>deptno,ename,hiredate,sal,</code><code>avg</code><code>(sal) over(partition </code><code>by</code> <code>deptno) </code><code>avg</code> <code>from</code> <code>emp;</code>
<code> </code><code>10 CLARK 1981-06-09 00:00:00 2450 2916.66667</code>
<code> </code><code>10 KING 1981-11-17 00:00:00 5000 2916.66667</code>
<code> </code><code>10 MILLER 1982-01-23 00:00:00 1300 2916.66667</code>
<code> </code><code>20 JONES 1981-04-02 00:00:00 2975 2175</code>
<code> </code><code>20 FORD 1981-12-03 00:00:00 3000 2175</code>
<code> </code><code>20 ADAMS 1987-05-23 00:00:00 1100 2175</code>
<code> </code><code>20 SMITH 1980-12-17 00:00:00 800 2175</code>
<code> </code><code>20 SCOTT 1987-04-19 00:00:00 3000 2175</code>
<code> </code><code>30 WARD 1981-02-22 00:00:00 1250 1566.66667</code>
<code> </code><code>30 TURNER 1981-09-08 00:00:00 1500 1566.66667</code>
<code> </code><code>30 ALLEN 1981-02-20 00:00:00 1600 1566.66667</code>
<code> </code><code>30 JAMES 1981-12-03 00:00:00 950 1566.66667</code>
<code> </code><code>30 BLAKE 1981-05-01 00:00:00 2850 1566.66667</code>
<code> </code><code>30 MARTIN 1981-09-28 00:00:00 1250 1566.66667</code>
<code>scott@TEST></code><code>select</code> <code>deptno,</code><code>avg</code><code>(sal) </code><code>from</code> <code>emp </code><code>group</code> <code>by</code> <code>deptno;</code>
<code> </code><code>DEPTNO </code><code>AVG</code><code>(SAL)</code>
<code>---------- ----------</code>
<code> </code><code>30 1566.66667</code>
<code> </code><code>20 2175</code>
<code> </code><code>10 2916.66667</code>
从输出可以看出,AVG计算出了每个部门的平均值,并输出到对应的行。
eg3:使用order_by_clause
<code>scott@TEST></code><code>select</code> <code>deptno,ename,hiredate,sal,</code><code>avg</code><code>(sal) over(partition </code><code>by</code> <code>deptno </code><code>order</code> <code>by</code> <code>sal) </code><code>avg</code> <code>from</code> <code>emp;</code>
<code> </code><code>10 MILLER 1982-01-23 00:00:00 1300 1300</code>
<code> </code><code>10 CLARK 1981-06-09 00:00:00 2450 1875</code>
<code> </code><code>20 SMITH 1980-12-17 00:00:00 800 800</code>
<code> </code><code>20 ADAMS 1987-05-23 00:00:00 1100 950</code>
<code> </code><code>20 JONES 1981-04-02 00:00:00 2975 1625</code>
<code> </code><code>30 JAMES 1981-12-03 00:00:00 950 950</code>
<code> </code><code>30 MARTIN 1981-09-28 00:00:00 1250 1150</code>
<code> </code><code>30 WARD 1981-02-22 00:00:00 1250 1150</code>
<code> </code><code>30 TURNER 1981-09-08 00:00:00 1500 1237.5</code>
<code> </code><code>30 ALLEN 1981-02-20 00:00:00 1600 1310</code>
从输出结果可以看出,每个部门的行都按sal做了升序排序。
eg4:使用windowing_clause
<code>scott@TEST></code><code>select</code> <code>deptno,ename,hiredate,sal,</code><code>avg</code><code>(sal) over(partition </code><code>by</code> <code>deptno </code><code>order</code> <code>by</code> <code>sal </code><code>rows</code> <code>BETWEEN</code> <code>1 PRECEDING </code><code>AND</code> <code>1 FOLLOWING) </code><code>avg</code> <code>from</code> <code>emp;</code>
<code> </code><code>10 MILLER 1982-01-23 00:00:00 1300 1875</code>
<code> </code><code>10 KING 1981-11-17 00:00:00 5000 3725</code>
<code> </code><code>20 SMITH 1980-12-17 00:00:00 800 950</code>
<code> </code><code>20 ADAMS 1987-05-23 00:00:00 1100 1625</code>
<code> </code><code>20 JONES 1981-04-02 00:00:00 2975 2358.33333</code>
<code> </code><code>20 SCOTT 1987-04-19 00:00:00 3000 2991.66667</code>
<code> </code><code>20 FORD 1981-12-03 00:00:00 3000 3000</code>
<code> </code><code>30 JAMES 1981-12-03 00:00:00 950 1100</code>
<code> </code><code>30 WARD 1981-02-22 00:00:00 1250 1333.33333</code>
<code> </code><code>30 TURNER 1981-09-08 00:00:00 1500 1450</code>
<code> </code><code>30 ALLEN 1981-02-20 00:00:00 1600 1983.33333</code>
<code> </code><code>30 BLAKE 1981-05-01 00:00:00 2850 2225</code>
从输出的结果可以看出,分析函数对每一组中的每一行的输出结果是把它自己与它的上一行和下一行这三行求平均值。
分析函数太多,这里就不一一介绍功能了,有兴趣的同学可以点开上面的连接,去查看对应的功能。
本文转自hbxztc 51CTO博客,原文链接:http://blog.51cto.com/hbxztc/1918614,如需转载请自行联系原作者