分析函数是oracle816引入的一个全新的概念,为我们分析数据提供了一种简单高效的处理方式.在分析函数出现以前,我们必须使用自联查询,子查询或者内联视图,甚至复杂的存储过程实现的语句,现在只要一条简单的sql语句就可以实现了,而且在执行效率方面也有相当大的提高.
下面主要介绍一下以下几个函数的使用方法
1. Over() 开窗函数
2. Nvl()函数
3. Rollup,Cube自动汇总函数
4. Rank,Dense_rank,Row_number函数
5. Lag , Lead函数
6. Sum,Avg, Count, Max函数
7. Ratio_to_report报表处理函数
8. First,Last,First_value,Last_value取基数的分析函数
9. Greatest, Least 函数
10. Trunc, Round,Decode, Substr函数
一. Over() 开窗函数
Over() 开窗函数是Oracle的分析函数,其语法如下:
函数名([ 参数 ]) over( [ 分区子句 ] [ 排序子句 [ 滑动窗口子句 ] ])
分区子句类似于聚组函数所需要的group by,排序子句可看成是SQL语句中的order by,只不过在此语句中还可指定null值排前(nulls first)还是排后(nulls last)。
开窗函数指定了分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化,举例如下:
over(order by salary) 按照salary排序进行累计,order by是个默认的开窗函数
over(partition by deptno)按照部门分区
over(order by salary range between 50 preceding and 150 following)
每行对应的数据窗口是之前行幅度值不超过50,之后行幅度值不超过150
over(order by salary rows between 50 preceding and 150 following)
每行对应的数据窗口是之前50行,之后150行
over(order by salary rows between unbounded preceding and unbounded following)
每行对应的数据窗口是从第一行到最后一行,等效:
over(order by salary range between unbounded preceding and unbounded following)
二.Nvl() 函数
NVL(EXP1,EXP2),函数返回exp1和exp2 中第一个不为空的值。
如果exp1为空则返回exp2,否则返回exp1。
注意:如果exp1不是字符串,那么返回的数据类型和exp1的数据类型相同,否则返回的数据类型为varchar2型。
SQL> select nvl('This is not null', 7) Frist, nvl(null, 'My Oracle') Second from dual;
FRIST SECOND
------------------ -------------
This is not null My Oracle
三. 自动汇总函数rollup,cube
Rollup:表示的意思是:除了分组的功能外,还进行累加的的,多了一个汇总。
如果是 GROUP BY ROLLUP(A, B, C) 的话, GROUP BY 顺序
(A 、 B 、 C)
(A 、 B)
(A)
最后对全表进行 GROUP BY 操作。
Cube提供了按照多字段汇总的功能。
如果是 GROUP BY CUBE(A, B, C) , GROUP BY 顺序
(A 、 B 、 C)
(A 、 B)
(A 、 C)
(A) ,
(B 、 C)
(B)
(C) ,
最后对全表进行 GROUP BY 操作。
示例:
CREATE TABLE studentscore
(
student_name varchar2(20),
subjects varchar2(20),
score number
)
INSERT INTO studentscore VALUES('WBQ','ENGLISH',90);
INSERT INTO studentscore VALUES('WBQ','MATHS',95);
INSERT INTO studentscore VALUES('WBQ','CHINESE',88);
INSERT INTO studentscore VALUES('CZH','ENGLISH',80);
INSERT INTO studentscore VALUES('CZH','MATHS',90);
INSERT INTO studentscore VALUES('CZH','HISTORY',92);
INSERT INTO studentscore VALUES('CB','POLITICS',70);
INSERT INTO studentscore VALUES('CB','HISTORY',75);
INSERT INTO studentscore VALUES('LDH','POLITICS',80);
INSERT INTO studentscore VALUES('LDH','CHINESE',90);
INSERT INTO studentscore VALUES('LDH','HISTORY',95);
select * from studentscore;
/* Formatted on 2009/11/08 20:35 (Formatter Plus v4.8.8) */
SELECT student_name, subjects, SUM (score)
FROM studentscore
GROUP BY CUBE (student_name, subjects)
ORDER BY 1;
等同于以下标准 SQL
/* Formatted on 2009/11/08 20:35 (Formatter Plus v4.8.8) */
SELECT NULL, subjects, SUM (score)
FROM studentscore
GROUP BY subjects
UNION
SELECT student_name, NULL, SUM (score)
FROM studentscore
GROUP BY student_name
UNION
SELECT NULL, NULL, SUM (score)
FROM studentscore
UNION
SELECT student_name, subjects, SUM (score)
FROM studentscore
GROUP BY student_name, subjects
/* Formatted on 2009/11/08 20:35 (Formatter Plus v4.8.8) */
SELECT student_name, subjects, SUM (score)
FROM studentscore
GROUP BY ROLLUP (student_name, subjects);
/* Formatted on 2009/11/08 20:35 (Formatter Plus v4.8.8) */
SELECT student_name, NULL, SUM (score)
FROM studentscore
GROUP BY student_name
UNION
SELECT NULL, NULL, SUM (score)
FROM studentscore
UNION
SELECT student_name, subjects, SUM (score)
FROM studentscore
GROUP BY student_name, subjects
/* Formatted on 2009/11/08 20:35 (Formatter Plus v4.8.8) */
SELECT GROUPING (student_name), GROUPING (subjects), student_name, subjects,
SUM (score)
FROM studentscore
GROUP BY CUBE (student_name, subjects)
ORDER BY 1, 2;
/* Formatted on 2009/11/08 20:36 (Formatter Plus v4.8.8) */
SELECT GROUPING (student_name), GROUPING (subjects), student_name, subjects,
SUM (score)
FROM studentscore
GROUP BY ROLLUP (student_name, subjects)
ORDER BY 1, 2;
/* Formatted on 2009/11/08 20:36 (Formatter Plus v4.8.8) */
SELECT GROUPING_ID (student_name, subjects), student_name, subjects,
SUM (score)
FROM studentscore
GROUP BY CUBE (student_name, subjects)
ORDER BY 1;
/* Formatted on 2009/11/08 20:36 (Formatter Plus v4.8.8) */
SELECT GROUPING_ID (student_name, subjects), student_name, subjects,
SUM (score)
FROM studentscore
GROUP BY ROLLUP (student_name, subjects)
ORDER BY 1;
/* Formatted on 2009/11/08 20:36 (Formatter Plus v4.8.8) */
SELECT GROUPING (student_name), GROUPING (subjects),
CASE
WHEN GROUPING (student_name) = 0
AND GROUPING (subjects) = 1
THEN ' 学生成绩合计 '
WHEN GROUPING (student_name) = 1
AND GROUPING (subjects) = 0
THEN ' 课目成绩合计 '
WHEN GROUPING (student_name) = 1
AND GROUPING (subjects) = 1
THEN ' 总 计 '
ELSE ''
END summary,
student_name, subjects, SUM (score)
FROM studentscore
GROUP BY CUBE (student_name, subjects)
ORDER BY 1, 2;
四. rank, dense_rank,row_number函数
Rank,Dense_rank,Row_number函数为每条记录产生一个从1开始至N的自然数,N的值可能小于等于记录的总数。这3个函数的唯一区别在于当碰到相同数据时的排名策略。
① ROW_NUMBER:
Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
② DENSE_RANK:
Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。
③ RANK:
Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的,同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
示例:
/* Formatted on 2009/11/08 20:48 (Formatter Plus v4.8.8) */
SELECT ename, deptno, sal,
RANK () OVER (PARTITION BY deptno ORDER BY sal DESC) "RANK",
DENSE_RANK () OVER (PARTITION BY deptno ORDER BY sal DESC) "DENSE_RANK",
ROW_NUMBER () OVER (PARTITION BY deptno ORDER BY sal DESC) "ROW_NUMBER"
FROM scott.emp
ENAME |
DEPTNO |
SAL |
RANK |
DENSE_RANK |
ROW_NUMBER |
KING |
10 |
5,000 |
1 |
1 |
1 |
CLARK |
10 |
2,450 |
2 |
2 |
2 |
MILLER |
10 |
1,300 |
3 |
3 |
3 |
SCOTT |
20 |
3,000 |
1 |
1 |
1 |
FORD |
20 |
3,000 |
1 |
1 |
2 |
JONES |
20 |
2,975 |
3 |
2 |
3 |
ADAMS |
20 |
1,100 |
4 |
3 |
4 |
SMITH |
20 |
800 |
5 |
4 |
5 |
BLAKE |
30 |
2,850 |
1 |
1 |
1 |
ALLEN |
30 |
1,600 |
2 |
2 |
2 |
TURNER |
30 |
1,500 |
3 |
3 |
3 |
MARTIN |
30 |
1,250 |
4 |
4 |
4 |
WARD |
30 |
1,250 |
4 |
4 |
5 |
JAMES |
30 |
950 |
6 |
5 |
6 |
五. lag,lead函数
lag(expression,<offset>,<default>) 函数可以访问组内当前行之前的行,
lead(expression,<offset>,<default>) 函数则正相反,可以反问组内当前行之后的行.
其中,offset是正整数,默认为1.因组内第一个条记录没有之前的行,最后一行没有之后的行,它表示要取列第N行之前或者之后的值,default就是用于处理这样的信息,默认为空.它用于当之前或者之后第N行不存在时的值。
注意:这2个函数必须指定 order By 字句.
/* Formatted on 2009/11/08 21:09 (Formatter Plus v4.8.8) */
SELECT ename, deptno, sal, LAG (sal) OVER (ORDER BY sal) LAG,
LEAD (sal) OVER (ORDER BY sal) LEAD
FROM scott.emp;
ENAME |
DEPTNO |
SAL |
LAG |
LEAD |
SMITH |
20 |
800 |
|
950 |
JAMES |
30 |
950 |
800 |
1,100 |
ADAMS |
20 |
1,100 |
950 |
1,250 |
WARD |
30 |
1,250 |
1,100 |
1,250 |
MARTIN |
30 |
1,250 |
1,250 |
1,300 |
MILLER |
10 |
1,300 |
1,250 |
1,500 |
TURNER |
30 |
1,500 |
1,300 |
1,600 |
ALLEN |
30 |
1,600 |
1,500 |
2,450 |
CLARK |
10 |
2,450 |
1,600 |
2,850 |
BLAKE |
30 |
2,850 |
2,450 |
2,975 |
JONES |
20 |
2,975 |
2,850 |
3,000 |
SCOTT |
20 |
3,000 |
2,975 |
3,000 |
FORD |
20 |
3,000 |
3,000 |
5,000 |
KING |
10 |
5,000 |
3,000 |
|
/* Formatted on 2009/11/08 21:11 (Formatter Plus v4.8.8) */
SELECT ename, deptno, sal, LAG (sal, 2, 0) OVER (ORDER BY sal) LAG,
LEAD (sal, 2, sal) OVER (ORDER BY sal) LEAD
FROM scott.emp;
ENAME |
DEPTNO |
SAL |
LAG |
LEAD |
SMITH |
20 |
800 |
0 |
1,100 |
JAMES |
30 |
950 |
0 |
1,250 |
ADAMS |
20 |
1,100 |
800 |
1,250 |
WARD |
30 |
1,250 |
950 |
1,300 |
MARTIN |
30 |
1,250 |
1,100 |
1,500 |
MILLER |
10 |
1,300 |
1,250 |
1,600 |
TURNER |
30 |
1,500 |
1,250 |
2,450 |
ALLEN |
30 |
1,600 |
1,300 |
2,850 |
CLARK |
10 |
2,450 |
1,500 |
2,975 |
BLAKE |
30 |
2,850 |
1,600 |
3,000 |
JONES |
20 |
2,975 |
2,450 |
3,000 |
SCOTT |
20 |
3,000 |
2,850 |
5,000 |
FORD |
20 |
3,000 |
2,975 |
3,000 |
KING |
10 |
5,000 |
3,000 |
5,000 |
六. sum,avg, count,max 函数
6.1 SUM 函数
/* Formatted on 2009/11/08 21:25 (Formatter Plus v4.8.8) */
SELECT SUM (sal) "sum"
FROM scott.emp;
/* Formatted on 2009/11/08 21:27 (Formatter Plus v4.8.8) */
SELECT ename, deptno, sal,
SUM (sal) OVER (PARTITION BY deptno ORDER BY sal RANGE UNBOUNDED PRECEDING) "SUM"
FROM scott.emp;
ENAME |
DEPTNO |
SAL |
SUM |
MILLER |
10 |
1,300 |
1,300 |
CLARK |
10 |
2,450 |
3,750 |
KING |
10 |
5,000 |
8,750 |
SMITH |
20 |
800 |
800 |
ADAMS |
20 |
1,100 |
1,900 |
JONES |
20 |
2,975 |
4,875 |
SCOTT |
20 |
3,000 |
10,875 |
FORD |
20 |
3,000 |
10,875 |
JAMES |
30 |
950 |
950 |
MARTIN |
30 |
1,250 |
3,450 |
WARD |
30 |
1,250 |
3,450 |
TURNER |
30 |
1,500 |
4,950 |
ALLEN |
30 |
1,600 |
6,550 |
BLAKE |
30 |
2,850 |
9,400 |
6.2 AVG 函数
/* Formatted on 2009/11/08 21:29 (Formatter Plus v4.8.8) */
SELECT AVG (sal) "avg"
FROM scott.emp;
/* Formatted on 2009/11/08 21:31 (Formatter Plus v4.8.8) */
SELECT ename, deptno, sal,hiredate,
round((AVG (sal) OVER (PARTITION BY deptno ORDER BY hiredate
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)),2) "c_mavg"
FROM scott.emp;
Round() 取小数点后面2位
ENAME DEPTNO SAL HIREDATE c_mavg
CLARK 10 2450 1981-6-9 3725
KING 10 5000 1981-11-17 2916.67
MILLER 10 1300 1982-1-23 3150
SMITH 20 800 1980-12-17 1887.5
JONES 20 2975 1981-4-2 2258.33
FORD 20 3000 1981-12-3 2991.67
SCOTT 20 3000 1987-4-19 2366.67
ADAMS 20 1100 1987-5-23 2050
ALLEN 30 1600 1981-2-20 1425
WARD 30 1250 1981-2-22 1900
BLAKE 30 2850 1981-5-1 1866.67
TURNER 30 1500 1981-9-8 1866.67
MARTIN 30 1250 1981-9-28 1233.33
JAMES 30 950 1981-12-3 1100