8i | 9i | 10g | 11g | 12c | 13c | 18c | 19c | 21c | 23ai | Misc | PL/SQL | SQL | RAC | WebLogic | Linux
FIRST and LAST Analytic Functions
This article gives an overview of the FIRST
and LAST
analytic functions. If you are new to analytic functions you should probably read this introduction to analytic functions first.
Most of the time I find myself using FIRST_VALUE and LAST_VALUE Analytic Functions in preference to FIRST
and LAST
. Pick which feels best for your use case.
Related articles.
Setup
The examples in this article require the following table.
--drop table emp purge; create table emp ( empno number(4) constraint pk_emp primary key, ename varchar2(10), job varchar2(9), mgr number(4), hiredate date, sal number(7,2), comm number(7,2), deptno number(2) ); insert into emp values (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,null,20); insert into emp values (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30); insert into emp values (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30); insert into emp values (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,null,20); insert into emp values (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30); insert into emp values (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,null,30); insert into emp values (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,null,10); insert into emp values (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,null,20); insert into emp values (7839,'KING','PRESIDENT',null,to_date('17-11-1981','dd-mm-yyyy'),5000,null,10); insert into emp values (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30); insert into emp values (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,null,20); insert into emp values (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,null,30); insert into emp values (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,null,20); insert into emp values (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,null,10); commit;
FIRST Analytic Function
The FIRST
analytic function can be used to return the first value from an ordered sequence. Say we want to display the salary of each employee, along with the lowest salary within their department we may use something like.
select empno, deptno, sal, min(sal) keep (dense_rank first order by sal) over (partition by deptno) as lowest from emp order by deptno, sal; EMPNO DEPTNO SAL LOWEST ---------- ---------- ---------- ---------- 7934 10 1300 1300 7782 10 2450 1300 7839 10 5000 1300 7369 20 800 800 7876 20 1100 800 7566 20 2975 800 7788 20 3000 800 7902 20 3000 800 7900 30 950 950 7654 30 1250 950 7521 30 1250 950 7844 30 1500 950 7499 30 1600 950 7698 30 2850 950 SQL>
The MIN
function is almost irrelevant here as it's FIRST
and KEEP
that are picking the row whose value will be used. We can demonstrate this by using MAX
for the low value.
select empno, deptno, sal, max(sal) keep (dense_rank first order by sal) over (partition by deptno) as lowest from emp order by deptno, sal; EMPNO DEPTNO SAL LOWEST ---------- ---------- ---------- ---------- 7934 10 1300 1300 7782 10 2450 1300 7839 10 5000 1300 7369 20 800 800 7876 20 1100 800 7566 20 2975 800 7788 20 3000 800 7902 20 3000 800 7900 30 950 950 7654 30 1250 950 7521 30 1250 950 7844 30 1500 950 7499 30 1600 950 7698 30 2850 950 SQL>
We get the same result.
We could also achieve the same result using FIRST_VALUE
or MIN
as basic analytic functions. In practice I don't use FIRST
very often.
LAST Analytic Function
The LAST
analytic function can be used to return the last value from an ordered sequence. Say we want to display the salary of each employee, along with the highest within their department we may use something like.
select empno, deptno, sal, max(sal) keep (dense_rank last order by sal) over (partition by deptno) as highest from emp order by deptno, sal; EMPNO DEPTNO SAL HIGHEST ---------- ---------- ---------- ---------- 7934 10 1300 5000 7782 10 2450 5000 7839 10 5000 5000 7369 20 800 3000 7876 20 1100 3000 7566 20 2975 3000 7788 20 3000 3000 7902 20 3000 3000 7900 30 950 2850 7654 30 1250 2850 7521 30 1250 2850 7844 30 1500 2850 7499 30 1600 2850 7698 30 2850 2850 SQL>
The MAX
function is almost irrelevant here as it's LAST
and KEEP
that are picking the row whose value will be used. We can demonstrate this by using MIN
for the high value.
select empno, deptno, sal, min(sal) keep (dense_rank last order by sal) over (partition by deptno) as highest from emp order by deptno, sal; EMPNO DEPTNO SAL HIGHEST ---------- ---------- ---------- ---------- 7934 10 1300 5000 7782 10 2450 5000 7839 10 5000 5000 7369 20 800 3000 7876 20 1100 3000 7566 20 2975 3000 7788 20 3000 3000 7902 20 3000 3000 7900 30 950 2850 7654 30 1250 2850 7521 30 1250 2850 7844 30 1500 2850 7499 30 1600 2850 7698 30 2850 2850 SQL>
We get the same result.
We could also achieve the same result using LAST_VALUE
or MAX
as basic analytic functions. In practice I don't use LAST
very often.
Quick Links
The "*" indicates the function supports the full analytic syntax, including the windowing clause.
For more information see:
- Analytic Functions : All Articles
- Analytic Functions
- FIRST_VALUE and LAST_VALUE Analytic Functions
- FIRST
- LAST
Hope this helps. Regards Tim...