📖 Теория
⚡ Кратко: теория
Функции смещения и выбора позволяют смотреть не только на текущую строку, но и на соседние или крайние строки внутри окна.
LAG() возвращает значение из предыдущей строки, а LEAD() — из следующей строки в порядке, заданном внутри OVER.
FIRST_VALUE(), LAST_VALUE() и NTH_VALUE() выбирают первое, последнее или n-е значение в окне.
Ключевая конструкция урока: function(column) OVER (PARTITION BY group_column ORDER BY sort_column).
Минимальный пример: LAG(creation_date) OVER (PARTITION BY supplier_id ORDER BY creation_date) показывает предыдущую дату заказа поставщика.
Топ-3 ошибки: забыть ORDER BY, перепутать направление LEAD/LAG, использовать LAST_VALUE без явной рамки окна.
Что делают функции смещения
В источнике функции смещения и выбора описаны как оконные функции, которые зависят от значений в других строках в пределах заданного окна. Это удобно, когда нужно сравнить текущую строку с предыдущей, следующей или с крайним значением группы.
LAG(value)смотрит назад относительно текущей строки.LEAD(value)смотрит вперёд относительно текущей строки.FIRST_VALUE(value)берёт первое значение окна.LAST_VALUE(value)берёт последнее значение окна.NTH_VALUE(value, n)берёт n-е значение окна.
Общий синтаксис
Шаблон из источника:
SELECT column1,
window_function(column2) OVER (
PARTITION BY column3
ORDER BY column4
) AS result_column
FROM table_name;
PARTITION BY делит строки на независимые группы, а ORDER BY определяет, какая строка считается предыдущей, следующей, первой или последней.
Без ORDER BY функции смещения теряют смысл: база данных не обязана хранить строки в естественном порядке.
LEAD и LAG
LAG() нужен для ответа на вопрос «что было до текущей строки?», а LEAD() — «что будет после текущей строки?».
SELECT
supplier_id,
creation_date,
LAG(creation_date) OVER (
PARTITION BY supplier_id
ORDER BY creation_date
) AS previous_creation_date,
LEAD(creation_date) OVER (
PARTITION BY supplier_id
ORDER BY creation_date
) AS next_creation_date
FROM purchase_orders;
Здесь окно строится отдельно для каждого supplier_id. Поэтому предыдущая дата не перескакивает к другому поставщику.
FIRST_VALUE, LAST_VALUE и NTH_VALUE
FIRST_VALUE() удобно использовать, когда нужно показать крайнее значение группы рядом с каждой строкой: например, первую цену месяца или минимальную цену заказа.
LAST_VALUE() и NTH_VALUE() чувствительны к рамке окна: если рамка заканчивается текущей строкой, «последним» может оказаться текущее значение.
LAST_VALUE/NTH_VALUE зависит от window frame. Для «последнего значения всего раздела» обычно задают ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
SELECT
order_id,
unit_price,
LAST_VALUE(unit_price) OVER (
PARTITION BY order_id
ORDER BY unit_price
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS max_price_in_order
FROM purchase_order_details;