


LAG() возвращает значение из предыдущей строки окна. Чтобы сравнивать продажи внутри каждого магазина, укажите магазин в PARTITION BY, а день в ORDER BY. На Mentoring.digital разбираем случай, когда между двумя записями пропущен день.
В данных не больше одной записи на магазин и дату. Имена столбцов в примере обозначают магазин, день и число продаж. Сначала получаем предыдущие продажи, затем вычитаем их из текущих.
WITH sales(shop, day, units) AS (
VALUES
('A', DATE '2026-10-01', 10),
('A', DATE '2026-10-03', 15),
('B', DATE '2026-10-01', 7),
('B', DATE '2026-10-02', 5)
), compared AS (
SELECT shop, day, units,
lag(units) OVER (
PARTITION BY shop ORDER BY day
) AS previous_units
FROM sales
)
SELECT shop, day, units, previous_units,
units - previous_units AS change
FROM compared
ORDER BY shop, day;
У магазина A для 3 октября разница равна 5. Сравнение идёт с записью за 1 октября. У магазина B для 2 октября разница равна −2. Первая строка каждой группы получает NULL в обоих вычисляемых столбцах.
PARTITION BY начинает сравнение заново для каждого магазина. ORDER BY внутри OVER определяет, какую запись считать предыдущей. Если за день есть несколько строк, добавьте стабильный критерий, например идентификатор события, или сначала сгруппируйте продажи по дням. Внешний ORDER BY отвечает за порядок строк в выводе.
Добавьте в пример строку магазина A за 2 октября и пересчитайте разницу за 3-е. Затем уберите её и сравните результаты. Если задача требует сравнения с предыдущей календарной датой даже без продаж, сначала подготовьте ежедневный ряд и явно определите смысл пропуска. Ноль для первой строки ставьте только тогда, когда он действительно означает отсутствие продаж в предыдущем наблюдении.
Оконные запросы можно закрепить на практических занятиях по SQL. Свой ряд и порядок строк можно проверить с ментором по PostgreSQL.