LAST_VALUE возвращает зарплату самой строки вместо максимальной по отделу
Этот запрос должен ставить максимальную зарплату отдела в каждую строку, но top_salary вместо этого просто повторяет зарплату самой строки. Найдите причину и исправьте.
SELECT employee_id, department, salary,
LAST_VALUE(salary) OVER (PARTITION BY department ORDER BY salary) AS top_salary
FROM employees;
Найдите и исправьте ошибку.
При ORDER BY рамка RANGE по умолчанию кончается на текущей строке, поэтому LAST_VALUE возвращает зарплату самой строки. Расширяют её до UNBOUNDED FOLLOWING или берут MAX(salary) OVER (PARTITION BY department).
- ✗Винить направление сортировки, а не рамку по умолчанию
- ✗Думать, что
PARTITION BYперезапускается на строке, а не на группе - ✗Ожидать, что
LAST_VALUEпо умолчанию сканирует всю партицию
- →Почему
FIRST_VALUEздесь работает как ожидается, аLAST_VALUE— нет? - →Когда предпочесть
MAX() OVER (...)вместоLAST_VALUE?
Причина — рамка по умолчанию. Как только у окна есть ORDER BY, рамка становится RANGE UNBOUNDED PRECEDING AND CURRENT ROW, то есть заканчивается на текущей строке. Поэтому «последнее значение» — это всегда сама текущая строка.
Расширяют рамку до конца партиции:
SELECT employee_id, department, salary,
LAST_VALUE(salary) OVER (
PARTITION BY department ORDER BY salary
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS top_salary
FROM employees;
Проще и надёжнее — MAX(salary) OVER (PARTITION BY department), которому рамка не нужна. Смена направления сортировки или удаление партиции проблему не решают.