Собесов

Какие функции возвращают значения из соседних строк?

SQLОконные функцииЛёгкаяJunior

Условие

Какие функции SQL умеют возвращать значения из предыдущих/последующих строк для заданной строки таблицы?

Решение

LAG() и LEAD() — оконные функции для смещения по упорядоченному окну.

SELECT
  user_id,
  event_date,
  revenue,
  LAG(revenue)  OVER (PARTITION BY user_id ORDER BY event_date) AS prev_day,
  LEAD(revenue) OVER (PARTITION BY user_id ORDER BY event_date) AS next_day
FROM revenue;
  • LAG(col, n, default) — значение из строки на n позиций назад в окне (по умолчанию n=1, для первой строки — default или NULL).
  • LEAD(col, n, default) — то же, но вперёд.

Зачем это нужно

  • Разница с предыдущим днём: revenue - LAG(revenue) OVER (...).
  • Доля от предыдущего: revenue / NULLIF(LAG(revenue) OVER (...), 0).
  • Длительность сессии: next_event_ts - LAG(event_ts) OVER (...).
  • Разрыв в стрике: вычислить gaps в последовательности дат через event_date - LAG(event_date).

Родственные функции

Функция Смысл
FIRST_VALUE(col) Первое значение в окне
LAST_VALUE(col) Последнее значение в окне (но осторожно с фреймом — по умолчанию ограничен текущей строкой)
NTH_VALUE(col, n) n-е значение
ROW_NUMBER() / RANK() / DENSE_RANK() Нумерация строк
SUM/AVG OVER (...) Бегущие агрегаты

Подводные камни

  1. Забыть PARTITION BY — окно станет глобальным, и предыдущей строкой для пользователя B окажется последняя строка пользователя A. Считать «изменение от предыдущего дня этого пользователя» — нужен PARTITION BY user_id.
  2. Забыть ORDER BY внутри OVER — некоторые СУБД дадут ошибку, другие — недетерминированный результат.
  3. LAST_VALUE без расширения фрейма возвращает текущую строку (потому что фрейм по умолчанию RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW). Лечится RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.

Эталонный ответ

LAG и LEAD (оконные функции).

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти