Oracle FIRST_VALUE和LAST_VALUE函数
first_value和last_value都属于分析函数。根据Oracle官方文档的描述first_value返回一个排序数据集合的第一行,last_value返回一个排序数据集合的最后一行。根据描述它们好像是一对相反的函数,一个返回第一行,一个返回最后一行,事实真是这样吗?
拿scot.emp表的数据举例说明:
1* select deptno,sal from emp where deptno=10
21:45:18 SCOTT@ orcl>/
DEPTNO SAL
---------- ----------
10 2450
10 5000
10 1300
部门编号10有三个人他们的工资分别是2400,5000,1300
现在将工资按从少到多排序,使用first_value返回第一行数据,应该是1300
22:19:34 SCOTT@ orcl>select distinct deptno,first_value(sal) over(order by sal) first_sal,sal from emp where deptno=10
22:21:02 2 /
DEPTNO FIRST_SAL SAL
---------- ---------- ----------
10 1300 2450
10 1300 5000
10 1300 1300
同样将工资从少到多排序,使用last_value返回最后一行,应该是5000
1* select distinct deptno,last_value(sal) over(order by sal) last_sal,sal from emp where deptno=10
22:04:09 SCOTT@ orcl>/
DEPTNO LAST_SAL SAL
---------- ---------- ----------
10 2450 2450
10 5000 5000
10 1300 1300
为什么和预想的不一样,原来Oracle的分析函数都有一个窗口子句,两次查询都没有指定窗口子句,所以函数使用了默认的窗口子句:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。即窗口的上界是无界,下界是当前行。
对于1300它的上界是1300下界也是1300所以最后一行是1300
对于2450它的上界是1300下界是2450所以最后一行是2450
对于5000它的上界是1300下界是5000所以最后一行是5000
同样的分析方法也适用于first_value
如果想返回某一组的最后一个值,需要显示声明窗口子句,让窗口的上界无界,下界也是无界这样,该组的数据将共享一个窗口数据。(对于上面的例子就是上界1300下界5000)
22:19:29 SCOTT@ orcl>SELECT DISTINCT deptno
22:19:31 2 ,last_value(sal) over(ORDER BY sal rows BETWEEN unbounded preceding AND unbounded following) last_sal
22:19:31 3 ,sal
22:19:31 4 FROM emp
22:19:31 5 WHERE deptno = 10
22:19:33 6 /
DEPTNO LAST_SAL SAL
---------- ---------- ----------
10 5000 1300
10 5000 5000
10 5000 2450