Зарегистрируйтесь, чтобы продолжить обучение

PREV_VALUE SQL: Оконные функции

В этом уроке мы рассмотрим функции смещения. Их всего две:

  • LEAD()
  • LAG()

Синтаксис функций

LEAD(expression [, offset[, default_value]]) OVER(ORDER BY columns)
LAG(expression [, offset, default_value]]) OVER(ORDER BY columns)

LEAD()

Слово lead переводится с английского как «вести». С помощью этой функции мы ведем функцию к следующей строке — то есть обращаемся к данным из следующей строки набора данных. Эту функцию можно использовать, чтобы сравнить текущее значение со следующим.

У нее есть три параметра:

  • Столбец, для которого нужно вернуть значение следующего значения параметра.
  • Количество строк для смещения. По умолчанию это всегда одна строка, но мы можем поменять количество строк на любое, которое нам нужно.
  • Значение, которое нужно вернуть в том случае, если после смещения возвращается значение NULL.

Для примера посмотрим изменение цен на криптобирже.

SELECT
    id,
    price,
    date_and_time,
    LEAD(
        price
    ) OVER (
        PARTITION BY DATE(date_and_time)
    ) AS ld
FROM
    bitcoin_prices;
id price date_and_time ld
1 45000 2022-01-01T09:00:00.000Z 37000
2 37000 2022-01-01T12:00:00.000Z 57000
3 57000 2022-01-01T15:00:00.000Z 48000
4 48000 2022-01-01T18:00:00.000Z
5 49000 2022-01-02T09:00:00.000Z 40000
6 40000 2022-01-02T12:00:00.000Z 58000
7 58000 2022-01-02T15:00:00.000Z 52000
8 52000 2022-01-02T18:00:00.000Z
9 49000 2022-01-03T09:00:00.000Z 45000
10 45000 2022-01-03T12:00:00.000Z 65000
11 65000 2022-01-03T15:00:00.000Z
12 50000 2022-01-04T18:00:00.000Z 44000
13 44000 2022-01-04T09:00:00.000Z 58000
14 58000 2022-01-04T12:00:00.000Z 51000
15 51000 2022-01-04T15:00:00.000Z 54000
...

View on DB Fiddle

Посмотрим на значения в ld - в каждой строке мы получили значение из следующей строки. У некоторых строк значение - NULL, так как следующего значения в этой группе (партиции) нет.

Мы можем указать дефолтное значение, которое будет подставляться, если не найдено значение. Для этого необходимо передать в LEAD() шаг смещения и само значение

-- получение следующего значения
SELECT
    id,
    price,
    date_and_time,
    LEAD(
        price, 1, 0.0
    ) OVER (
        PARTITION BY DATE(date_and_time)
    ) AS ld
FROM
    bitcoin_prices
id price date_and_time ld
1 45000 2022-01-01T09:00:00.000Z 37000
2 37000 2022-01-01T12:00:00.000Z 57000
3 57000 2022-01-01T15:00:00.000Z 48000
4 48000 2022-01-01T18:00:00.000Z 0.0
5 49000 2022-01-02T09:00:00.000Z 40000
...

View on DB Fiddle

LAG()

Слово lag переводится как «задержка». Эта функция подобна LEAD(), но функция обращается к данным из предыдущей строки набора.

С помощью функции LAG() можно сравнить текущее значение с предыдущим. Она также имеет три параметра:

  • Столбец, который нужно вернуть.
  • Количество строк смещения.
  • Значение, на которое нужно сместить.

В целом, функция LAG() работает абсолютно так же, как и LEAD(), просто мы берем не последующие значения, а предыдущие.

-- получение предыдущего значения
SELECT
    id,
    price,
    date_and_time,
    LAG(
        price
    ) OVER (
        PARTITION BY DATE(date_and_time)
    ) AS lg
FROM
    bitcoin_prices
id price date_and_time lg
1 45000 2022-01-01T09:00:00.000Z
2 37000 2022-01-01T12:00:00.000Z 45000
3 57000 2022-01-01T15:00:00.000Z 37000
4 48000 2022-01-01T18:00:00.000Z 57000
5 49000 2022-01-02T09:00:00.000Z
...

View on DB Fiddle

Применение LEAD и LAG

С помощью LEAD() и LAG() мы можем вычислять изменение значений со временем. Например, так можно получить динамику цен.

Попробуем решить задачу по поиску роста цен, относительно предыдущего периода. Для этого находим, следующую и предыдущую цену. Наша цена должна быть больше предыдущей и меньше следующей

-- находим записи, когда у нас цены росли относительно предыдущих в эти же дни
WITH tab AS (
    SELECT
        price,
        date_and_time,
        LAG(price) OVER (
            PARTITION BY DATE(date_and_time)
        ) AS lg,
        LEAD(price) OVER (
            PARTITION BY DATE(date_and_time)
        ) AS ld
    FROM
        bitcoin_prices
    ORDER BY
        date_and_time
)

SELECT * FROM tab
WHERE (price > lg OR lg IS NULL) AND (price < ld OR ld IS NULL);
price date_and_time lg ld
65000 2022-01-03T15:00:00.000Z 45000
54000 2022-01-04T18:00:00.000Z 51000
58500 2022-02-03T15:00:00.000Z 40500
48600 2022-02-04T18:00:00.000Z 45900

View on DB Fiddle

Выводы

  • Функции LEAD() и LAG() в SQL используются для доступа к значениям следующей или предыдущей строки внутри результирующего набора.
  • Функция LAG() возвращает значение столбца из предыдущей строки, а функция LEAD() возвращает значение из следующей строки.
  • Обе функции могут использоваться с опциональными параметрами, такими как смещение (offset) и значением по умолчанию (default value), что делает их более гибкими.
  • Функции LEAD и LAG полезны при анализе временных рядов, сравнении текущих значений с предыдущими или следующими значениями, а также при выполнении различных операций с данными внутри запроса SQL.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff