Analytic functions compute an aggregate value based on a group of rows called window which determines the range of rows used to perform the calculations for the current row. Following are most used Analytic functions.
- RANK, DENSE_RANK and ROW_NUMBER
- LAG and LEAD
- FIRST_VALUE and LAST_VALUE
The FIRST_VALUE returns the first result of an ordered set from a window. The LAST_VALUE returns the last result of an ordered set from a window
Now the main thing here to understand is when we use order by clause in window clause the default windowing clause is set to "RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" and makes LAST_VALUE to result unexpected. We need to alter the windowing clause to "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" get the result which is expected from LAST_VALUE.
A windowing clause defines the group (or window) of rows within a particular partition that will be evaluated for analytic function computation.
- UNBOUNDED PRECEDING indicate that the window starts at the first row of the partition.
- UNBOUNDED FOLLOWING indicate that the window ends at the last row of the partition.
- CURRENT ROW specifies that the window begins or end at the current row or value depending on where you have used CURRENT ROW. like
Lets have simple examples of FIRST_VALUE and LAST_VALUE using EMP table of SCOTT schema.
FIRST_VALUE:
LAST_VALUE:
If we execute QUERY of LAST_VALUE without windowing clause, the default windowing clause will make LAST_VALUE to result unexpected as:
Related Posts:
- Oracle: Rank, Dense_Rank, Row_Number Analytic Functions
- LAG and LEAD - Analytic Function
- Fill Gaps in Sparse Data - Partitioned Outer Join
- Oracle: Getting Cumulative Sum (Running Total) Using Analytical Functions
- Top N query - 3rd highest salary
- RANK, DENSE_RANK and ROW_NUMBER
- LAG and LEAD
- FIRST_VALUE and LAST_VALUE
The FIRST_VALUE returns the first result of an ordered set from a window. The LAST_VALUE returns the last result of an ordered set from a window
Now the main thing here to understand is when we use order by clause in window clause the default windowing clause is set to "RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" and makes LAST_VALUE to result unexpected. We need to alter the windowing clause to "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING" get the result which is expected from LAST_VALUE.
A windowing clause defines the group (or window) of rows within a particular partition that will be evaluated for analytic function computation.
- UNBOUNDED PRECEDING indicate that the window starts at the first row of the partition.
- UNBOUNDED FOLLOWING indicate that the window ends at the last row of the partition.
- CURRENT ROW specifies that the window begins or end at the current row or value depending on where you have used CURRENT ROW. like
- range between CURRENT ROW and unbounded following
- range between unbounded preceding and CURRENT ROW
Lets have simple examples of FIRST_VALUE and LAST_VALUE using EMP table of SCOTT schema.
FIRST_VALUE:
SQL> select
2 empno, ename, deptno, sal,
3 first_value(sal) over (partition by deptno order by sal) first_sal
4 from scott.emp;
EMPNO ENAME DEPTNO SAL FIRST_SAL
---------- ---------- ---------- ---------- ----------
7934 MILLER 10 1300 1300
7782 CLARK 10 2450 1300
7839 KING 10 5000 1300
7369 SMITH 20 800 800
7876 ADAMS 20 1100 800
7566 JONES 20 2975 800
7788 SCOTT 20 3000 800
7902 FORD 20 3000 800
7900 JAMES 30 950 950
7654 MARTIN 30 1250 950
7521 WARD 30 1250 950
7844 TURNER 30 1500 950
7499 ALLEN 30 1600 950
7698 BLAKE 30 2850 950
14 rows selected.
LAST_VALUE:
SQL> select
2 empno, ename, deptno, sal,
3 last_value(sal) over (partition by deptno order by sal
4 range between unbounded preceding and unbounded following) last_sal
5 from scott.emp;
EMPNO ENAME DEPTNO SAL LAST_SAL
---------- ---------- ---------- ---------- ----------
7934 MILLER 10 1300 5000
7782 CLARK 10 2450 5000
7839 KING 10 5000 5000
7369 SMITH 20 800 3000
7876 ADAMS 20 1100 3000
7566 JONES 20 2975 3000
7788 SCOTT 20 3000 3000
7902 FORD 20 3000 3000
7900 JAMES 30 950 2850
7654 MARTIN 30 1250 2850
7521 WARD 30 1250 2850
7844 TURNER 30 1500 2850
7499 ALLEN 30 1600 2850
7698 BLAKE 30 2850 2850
14 rows selected.
If we execute QUERY of LAST_VALUE without windowing clause, the default windowing clause will make LAST_VALUE to result unexpected as:
SQL> select
2 empno, ename, deptno, sal,
3 last_value(sal) over (partition by deptno order by sal) last_sal
4 from scott.emp;
EMPNO ENAME DEPTNO SAL LAST_SAL
---------- ---------- ---------- ---------- ----------
7934 MILLER 10 1300 1300
7782 CLARK 10 2450 2450
7839 KING 10 5000 5000
7369 SMITH 20 800 800
7876 ADAMS 20 1100 1100
7566 JONES 20 2975 2975
7788 SCOTT 20 3000 3000
7902 FORD 20 3000 3000
7900 JAMES 30 950 950
7654 MARTIN 30 1250 1250
7521 WARD 30 1250 1250
7844 TURNER 30 1500 1500
7499 ALLEN 30 1600 1600
7698 BLAKE 30 2850 2850
14 rows selected.
Related Posts:
- Oracle: Rank, Dense_Rank, Row_Number Analytic Functions
- LAG and LEAD - Analytic Function
- Fill Gaps in Sparse Data - Partitioned Outer Join
- Oracle: Getting Cumulative Sum (Running Total) Using Analytical Functions
- Top N query - 3rd highest salary
Interesting....
ReplyDeleteI didnt realize that one had to use additional specifiers to make LAST_VALUE or FIRST_VALUE look across the partition
If it is a WINDOW function, it should, I would have thought, looked across the window (i.e.whole group of records within that window).
Thanks....
Eashwer Iyer
Agreed. I never use LAST_VALUE because I didn't understand the need for the specific RANGE clause. Instead I always used FIRST_VALUE, then added DESC to the ORDER BY clause. I think that's worked very time for me, but I'm glad to finally understand why LAST_VALUE failed.
ReplyDeleteThank you!