Смещение: LAG и LEAD
Содержание курса
Ловушка: отсутствие PARTITION BY смешивает строки разных категорий
Самая распространённая ошибка с LAG — забыть PARTITION BY, когда данные содержат несколько смысловых групп.
Предположим, запрос написан так:
SELECT
category,
month,
amount,
LAG(amount, 1, NULL) OVER (ORDER BY category, month) AS prev_amount
FROM monthly_sales
ORDER BY category, month;
Без PARTITION BY category окно охватывает все шесть строк сразу. После сортировки по category, month они выстраиваются в порядке: Книги-01, Книги-02, Книги-03, Электроника-01, Электроника-02, Электроника-03. LAG для строки «Электроника-01» смотрит на строку непосредственно перед ней в этом глобальном порядке — то есть на «Книги-03» со значением 600.
Результат будет таким:
| category | month | amount | prev_amount |
|---|---|---|---|
| Книги | 2024-01 | 500 | NULL |
| Книги | 2024-02 | 700 | 500 |
| Книги | 2024-03 | 600 | 700 |
| Электроника | 2024-01 | 1200 | 600 |
| Электроника | 2024-02 | 900 | 1200 |
| Электроника | 2024-03 | 1100 | 900 |
Строка «Электроника-01» получила prev_amount = 600 — это последнее значение из категории «Книги». Никакой ошибки выполнения не будет: запрос отработает тихо и вернёт правдоподобно выглядящие числа. Обнаружить проблему можно только если знать, что ожидать NULL для первого периода каждой категории.
Исправление одно — добавить PARTITION BY category:
LAG(amount, 1, NULL) OVER (PARTITION BY category ORDER BY month)
Теперь для строки «Электроника-01» окно начинается заново внутри раздела «Электроника», предшественника нет, и LAG честно возвращает NULL.
Практическое правило: если в данных есть смысловые группы (категория, пользователь, регион) и вы хотите смотреть на «предыдущий» элемент внутри группы — PARTITION BY обязателен.
