Problem z LAST_VALUE()
jest to, że domyślne reguły klauzul okienkowych usuwają wartości, których naprawdę potrzebujesz. Jest to bardzo subtelny problem i dotyczy wszystkich baz danych obsługujących tę funkcjonalność.
Pochodzi z bloga Oracle:
Chociaż jesteśmy przy temacie klauzul okienek, niejawna i niezmienna klauzula okna dla funkcji FIRST i LAST to ROWSBETWEEN UNBOUNDED PRECEDING I UNBOUNDED FOLLOWING, innymi słowy wszystkie wiersze w naszej partycji. Dla FIRST_VALUE i LAST_VALUE domyślną, ale zmienną klauzulą okienkową jest ROWS BETWEEN UNBOUNDED PRECEDINGAND CURRENT ROW, innymi słowy wykluczamy wiersze po bieżącym. Upuszczanie wierszy z dołu listy nie ma znaczenia, gdy szukamy pierwszego wiersza na liście ( FIRST_VALUE), ale ma to znaczenie, gdy szukamy ostatniego wiersza na liście (LAST_VALUE) więc zwykle będziesz musiał albo wyraźnie określić ROWS BETWEENUNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING podczas korzystania z LAST_VALUE, albo po prostu użyć FIRST_VALUE i odwrócić kolejność sortowania .
Dlatego po prostu użyj FIRST_VALUE()
. Robi to, co chcesz:
with test (id, session_ID, value) as (
(VALUES (0, 2, 100),
(1, 2, 120),
(2, 2, 140),
(3, 1, 900),
(4, 1, 800),
(5, 1, 500)
)
)
select id,
first_value(value) over (partition by session_ID order by id) as first_value_window,
first_value(value) over (partition by session_ID order by id desc) as first_value_window_desc
from test
order by id