Oto krótkie zapytanie ilustrujące zachowanie:
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's 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)
Wynik powyższego zapytania można zobaczyć tutaj (SQLFiddle tutaj ):
| 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 |
Niewiele osób myśli o niejawnych ramkach, które są stosowane do funkcji okna, które przyjmują ORDER BY klauzula. W tym przypadku okna domyślnie przyjmują ramkę RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . (RANGE to nie to samo co ROWS, ale to już inna historia). Pomyśl o tym w ten sposób:
- W wierszu z
v = 1uporządkowana ramka okna obejmujev IN (1) - W wierszu z
v = 2uporządkowana ramka okna obejmujev IN (1, 2) - W wierszu z
v = 3uporządkowana ramka okna obejmujev IN (1, 2, 3) - W wierszu z
v = 4uporządkowana ramka okna obejmujev IN (1, 2, 3, 4)
Jeśli chcesz zapobiec takiemu zachowaniu, masz dwie możliwości:
- Użyj wyraźnych
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGklauzula zamówionego funkcje okien - Nie używaj
ORDER BYklauzula w tych funkcjach okna, które pozwalają na ich pominięcie (jakoMAX(v) OVER())
Więcej szczegółów wyjaśniono w ten artykuł o LEAD() , LAG() , FIRST_VALUE() i LAST_VALUE()