План закупок в SQL: спрос на срок поставки и открытые заказы

Закупщик видит остаток пять единиц и заказывает ещё десять. Через неделю приезжает уже оформленная поставка, и склад получает избыток. Для предложения закупки нужно одновременно учесть спрос до прихода нового заказа, свободный запас и ожидаемые поступления. Построим прозрачный расчёт в SQLite.

Какие входы нужны для рекомендации

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

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

Из потребности вычитаем доступный остаток и подтверждённые открытые поставки, которые должны прийти не позднее расчётной даты поступления. Поставка через месяц не решит дефицит следующей недели. В примере incoming содержит только ещё не полученное количество действующих заказов, поэтому повторно вычитать уже принятую часть не нужно.

Почему рекомендация не равна всем продажам

Итоговое количество не может быть отрицательным: избыток запаса даёт нулевой заказ. Для дробной потребности требуется округление под единицу закупки. В учебных данных спрос и сроки дают целые значения, чтобы проверить формулу вручную. Для коробок добавьте размер упаковки и округляйте вверх до кратного ему количества.

Товар C не продавался в наблюдавшейся неделе, но имеет страховой минимум один. Поэтому правило предложит одну единицу. Если компания не хочет пополнять неподвижный ассортимент, это нужно добавить отдельным условием активности товара. Скрыв такой случай нулевым спросом, можно незаметно изменить политику минимального наличия.

WITH products(sku,lead_days,safety,available) AS (
 VALUES ('A',10,2,5),('B',3,2,10),('C',5,1,0)
), sales(sku,qty) AS (VALUES ('A',3),('A',4),('B',14)),
incoming(sku,due,qty) AS (
 VALUES ('A','2026-10-06',4),('A','2026-11-01',100),('B','2026-10-07',2)
), demand AS (
 SELECT sku,SUM(qty)/7.0 AS daily FROM sales GROUP BY sku
), computed AS (
 SELECT p.sku,COALESCE(d.daily,0)*p.lead_days AS lead_demand,
 p.safety,p.available+COALESCE(SUM(i.qty),0) AS supply
 FROM products p LEFT JOIN demand d USING(sku)
 LEFT JOIN incoming i ON i.sku=p.sku
 AND i.due<=date('2026-10-05','+'||p.lead_days||' days')
 GROUP BY p.sku,p.lead_days,p.safety,p.available,d.daily
)
SELECT sku,lead_demand,supply,MAX(0,lead_demand+safety-supply) AS order_qty
FROM computed ORDER BY sku;

Ожидаемые строки результата в порядке столбцов SELECT:

[["A", 10.0, 9, 3.0], ["B", 6.0, 12, 0], ["C", 0, 0, 1]]

Проверяем предложение по товарам

У A спрос на срок поставки равен десяти, страховой запас — два. Свободных единиц пять, ещё четыре придут вовремя. Предложение закупки равно трём. Поздние сто единиц не участвуют. У B запас вместе с ближайшей поставкой превышает потребность, поэтому новый заказ нулевой. C показывает действие политики минимума.

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

Как развивать расчёт

Сезонный или акционный спрос плохо описывается одной средней неделей. Начните с проверки дней отсутствия товара и плановых промо: низкие продажи могли быть ограничены запасом. Затем добавьте календарный прогноз по дням до поступления. Сама структура рекомендации сохранится, изменится способ получения lead_demand.

Если есть минимальная партия и кратность коробки, применяйте их после расчёта чистой потребности и показывайте эффект округления отдельно. Так руководитель увидит, какая часть закупки нужна для покрытия спроса, а какая возникла из условий поставщика.

Доступный остаток для формулы важно получить из согласованного расчёта: Остаток есть, продавать нельзя: как рассчитать доступный товар в SQL.

Следующий уровень SQL-практики

В «Продвинутом SQL» вы учитесь объединять несколько источников, строить временные расчёты и проверять результат на неполных данных. Курс даёт многошаговые задачи на SQLite с автоматической проверкой. Итоговая практика включает цельные кейсы и аналитическую витрину магазина. Откройте программу «Продвинутого SQL».

Продолжить на практике