分析函数的基本概念和语法 -> http://blog.csdn.net/fw0124/article/details/7842039
1) rank(),dense_rank(),row_number()
这几个函数区别是:
a)rank()是跳跃排序,有两个第1名时接下来就是第3名;
b)dense_rank()是连续排序,有两个第1名时接下来仍然跟着第2名;
c)row_number()是连续排序,并且有并列名次时,按照记录集中记录的顺序名次依次递增。
tony@ORCL1> select ename, sal, deptno,
2 rank() over(partition by deptno order by sal) rank,
3 dense_rank() over(partition by deptno order by sal) dense_rank,
4 row_number() over(partition by deptno order by sal) row_number
5 from emp;
ENAME SAL DEPTNO RANK DENSE_RANK ROW_NUMBER
---------- ---------- ---------- ---------- ---------- ----------
MILLER $1300.00 10 1 1 1
CLARK $2450.00 10 2 2 2
KING $5000.00 10 3 3 3
SMITH $800.00 20 1 1 1
ADAMS $1100.00 20 2 2 2
JONES $2975.00 20 3 3 3
SCOTT $3000.00 20 4 4 4
FORD $3000.00 20 4 4 5
JAMES $950.00 30 1 1 1
MARTIN $1250.00 30 2 2 2
WARD $1250.00 30 2 2 3
TURNER $1500.00 30 4 3 4
ALLEN $1600.00 30 5 4 5
BLAKE $2850.00 30 6 5 6
14 rows selected.
2) first(), last()
first,last需要和dense_rank结合使用,返回排在第一和最后的记录(集合)。语法:
aggregate_function KEEP (dense_rank first|last order by ...) [over([partition_clause])]
例如,查询各部门薪水最高和最低的人名。不带over子句, 作为聚合函数使用。
tony@ORCL1> column first format a20
tony@ORCL1> column last format a20
tony@ORCL1> select deptno,
2 wm_concat(ename) keep (dense_rank first order by sal desc) first,
3 wm_concat(ename) keep (dense_rank last order by sal desc) last
4 from emp group by deptno;
DEPTNO FIRST LAST
---------- -------------------- --------------------
10 KING MILLER
20 SCOTT,FORD SMITH
30 BLAKE JAMES
查询各部门薪水最高和最低的人名。带over子句, 作为分析函数使用。
tony@ORCL1> select ename, sal, deptno,
2 wm_concat(ename) keep (dense_rank first order by sal desc)
3 over(partition by deptno) first,
4 wm_concat(ename) keep (dense_rank last order by sal desc)
5 over(partition by deptno) last
6 from emp;
ENAME SAL DEPTNO FIRST LAST
---------- ---------- ---------- -------------------- ---------
CLARK $2450.00 10 KING MILLER
KING $5000.00 10 KING MILLER
MILLER $1300.00 10 KING MILLER
JONES $2975.00 20 FORD,SCOTT SMITH
FORD $3000.00 20 FORD,SCOTT SMITH
ADAMS $1100.00 20 FORD,SCOTT SMITH
SMITH $800.00 20 FORD,SCOTT SMITH
SCOTT $3000.00 20 FORD,SCOTT SMITH
WARD $1250.00 30 BLAKE JAMES
TURNER $1500.00 30 BLAKE JAMES
ALLEN $1600.00 30 BLAKE JAMES
JAMES $950.00 30 BLAKE JAMES
BLAKE $2850.00 30 BLAKE JAMES
MARTIN $1250.00 30 BLAKE JAMES
14 rows selected.
3) first_value(), last_value()
first_value()和last_value()返回数据集合中的第一个值和最后一个值。
和first(),last()区别是仅仅返回1个值。
下面的例子,并不能得到期待结果。
原因是没有指定开窗子句,
order by会加上一个默认窗口RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
tony@ORCL1> select ename, sal, deptno,
2 first_value(ename) over (partition by deptno order by sal desc) first,
3 last_value(ename) over (partition by deptno order by sal desc) last
4 from emp;
ENAME SAL DEPTNO FIRST LAST
---------- ---------- ---------- -------------------- --------------------
KING $5000.00 10 KING KING
CLARK $2450.00 10 KING CLARK
MILLER $1300.00 10 KING MILLER
FORD $3000.00 20 FORD SCOTT
SCOTT $3000.00 20 FORD SCOTT
JONES $2975.00 20 FORD JONES
ADAMS $1100.00 20 FORD ADAMS
SMITH $800.00 20 FORD SMITH
BLAKE $2850.00 30 BLAKE BLAKE
ALLEN $1600.00 30 BLAKE ALLEN
TURNER $1500.00 30 BLAKE TURNER
MARTIN $1250.00 30 BLAKE WARD
WARD $1250.00 30 BLAKE WARD
JAMES $950.00 30 BLAKE JAMES
14 rows selected.
加上开窗子句,指定窗口为所有行,就可以得到期待结果。
tony@ORCL1> select ename, sal, deptno,
2 first_value(ename) over (partition by deptno order by sal desc
3 rows between unbounded preceding and unbounded following) first,
4 last_value(ename) over (partition by deptno order by sal desc
5 rows between unbounded preceding and unbounded following) last
6 from emp;
ENAME SAL DEPTNO FIRST LAST
---------- ---------- ---------- -------------------- --------------------
KING $5000.00 10 KING MILLER
CLARK $2450.00 10 KING MILLER
MILLER $1300.00 10 KING MILLER
SCOTT $3000.00 20 SCOTT SMITH
FORD $3000.00 20 SCOTT SMITH
JONES $2975.00 20 SCOTT SMITH
ADAMS $1100.00 20 SCOTT SMITH
SMITH $800.00 20 SCOTT SMITH
BLAKE $2850.00 30 BLAKE JAMES
ALLEN $1600.00 30 BLAKE JAMES
TURNER $1500.00 30 BLAKE JAMES
MARTIN $1250.00 30 BLAKE JAMES
WARD $1250.00 30 BLAKE JAMES
JAMES $950.00 30 BLAKE JAMES
14 rows selected.
4) lag(), lead()
lag()返回指定行之前的某个偏移位置的数据。
lead()和lag()相反,返回的是指定行之后的某个偏移位置的数据。
语法:
lag(value_expr[,offset[,default]]) over ([partition_clause] order_by_clause)
lead(value_expr[,offset[,default]]) over ([partition_clause] order_by_clause)
a) value_expr是想要返回的数据列;
b) offset是偏移位置,如果省略默认为1;
c) default是当偏移位置超出了组内的数据窗口的时候的返回值,如果省略默认为null。
tony@ORCL1> select ename, sal, deptno,
2 lag(sal, 2) over(partition by deptno order by sal) lag,
3 lead(sal, 2) over(partition by deptno order by sal) lead
4 from emp;
ENAME SAL DEPTNO LAG LEAD
---------- ---------- ---------- ---------- ----------
MILLER $1300.00 10 5000
CLARK $2450.00 10
KING $5000.00 10 1300
SMITH $800.00 20 2975
ADAMS $1100.00 20 3000
JONES $2975.00 20 800 3000
SCOTT $3000.00 20 1100
FORD $3000.00 20 2975
JAMES $950.00 30 1250
MARTIN $1250.00 30 1500
WARD $1250.00 30 950 1600
TURNER $1500.00 30 1250 2850
ALLEN $1600.00 30 1250
BLAKE $2850.00 30 1500
14 rows selected.