Here is a quick query to illustrate the behavior:
select v, -- FIRST_VALUE() and LAST_VALUE() first_value(v) over(order by v) f1, first_value(v) over(order by v rows between unbounded preceding and current row) f2, first_value(v) over(order by v rows between unbounded preceding and unbounded following) f3, last_value (v) over(order by v) l1, last_value (v) over(order by v rows between unbounded preceding and current row) l2, last_value (v) over(order by v rows between unbounded preceding and unbounded following) l3, -- For completeness' sake, let also compare the above with MAX() max (v) over() m1, max (v) over(order by v) m2, max (v) over(order by v rows between unbounded preceding and current row) m3, max (v) over(order by v rows between unbounded preceding and unbounded following) m4 from (values(1),(2),(3),(4)) t(v)
The output of the above query can be seen here ( SQLFiddle here ):
| V | F1 | F2 | F3 | L1 | L2 | L3 | M1 | M2 | M3 | M4 | |---|----|----|----|----|----|----|----|----|----|----| | 1 | 1 | 1 | 1 | 1 | 1 | 4 | 4 | 1 | 1 | 4 | | 2 | 1 | 1 | 1 | 2 | 2 | 4 | 4 | 2 | 2 | 4 | | 3 | 1 | 1 | 1 | 3 | 3 | 4 | 4 | 3 | 3 | 4 | | 4 | 1 | 1 | 1 | 4 | 4 | 4 | 4 | 4 | 4 | 4 |
Few people think of implicit frames that apply to window functions that accept an ORDER BY . In this case, the windows default to the RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW frame. (RANGE is not exactly the same as ROWS, but that's a different story). Think of it this way:
- On a line with
v = 1 ordered window frame spans v IN (1) - On a line with
v = 2 ordered window frame spans v IN (1, 2) - On a line with
v = 3 ordered window frame spans v IN (1, 2, 3) - On a line with
v = 4 ordered window frame spans v IN (1, 2, 3, 4)
If you want to prevent this behavior, you have two options:
- Use the explicit
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING for ordered window functions - Do not use the
ORDER BY in these window functions that allow them to be excluded (like MAX(v) OVER() )
See LEAD() , LAG() , FIRST_VALUE() and LAST_VALUE()
Lukas Eder
source share