Как посчитать stockout rate в SQL

Закрепи формулу stockout rate в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать stockout rate в Telegram

Зачем stockout rate

Когда товара нет на складе — теряем продажи, customer goes to competitor. Stockout rate — главная operational метрика retail/e-com. 5% stockout = 5% потерянных продаж минимум. Снижение rate напрямую растит revenue без новых customers.

Формула

stockout_rate = (SKU-hours with zero inventory) / (total SKU-hours)

Или проще: доля дней-SKU с нулевым остатком.

Stockout в SQL

WITH inventory_snapshots AS (
    SELECT
        sku_id,
        warehouse_id,
        snapshot_date,
        quantity_on_hand
    FROM inventory_history
    WHERE snapshot_date >= CURRENT_DATE - INTERVAL '30 days'
)
SELECT
    sku_id,
    COUNT(*) AS observations,
    SUM(CASE WHEN quantity_on_hand = 0 THEN 1 ELSE 0 END) AS stockout_observations,
    SUM(CASE WHEN quantity_on_hand = 0 THEN 1 ELSE 0 END)::NUMERIC * 100
    / NULLIF(COUNT(*), 0) AS stockout_pct
FROM inventory_snapshots
GROUP BY sku_id
ORDER BY stockout_pct DESC
LIMIT 50;

Топ SKU с stockout — flagship products, требующие приоритетного reorder.

Lost sales estimate

Сколько продали бы при наличии:

WITH baseline_velocity AS (
    SELECT
        sku_id,
        AVG(units_sold_per_day) AS avg_daily_sales
    FROM sku_sales_history
    WHERE in_stock = TRUE
      AND sale_date >= CURRENT_DATE - INTERVAL '60 days'
    GROUP BY sku_id
),
stockout_days AS (
    SELECT
        sku_id,
        COUNT(DISTINCT stockout_date) AS days_out
    FROM inventory_history
    WHERE quantity_on_hand = 0
      AND snapshot_date >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY sku_id
)
SELECT
    s.sku_id,
    s.days_out,
    b.avg_daily_sales,
    s.days_out * b.avg_daily_sales AS estimated_lost_units,
    s.days_out * b.avg_daily_sales * sku.price AS estimated_lost_revenue
FROM stockout_days s
JOIN baseline_velocity b USING (sku_id)
JOIN sku_pricing sku USING (sku_id)
ORDER BY estimated_lost_revenue DESC
LIMIT 50;

Estimate lost revenue даёт sense, насколько важна prevention.

Закрепи формулу stockout rate в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать stockout rate в Telegram

По SKU и складу

SELECT
    warehouse_id,
    COUNT(DISTINCT sku_id) AS active_skus,
    COUNT(DISTINCT CASE WHEN quantity_on_hand = 0 THEN sku_id END) AS sku_in_stockout,
    COUNT(DISTINCT CASE WHEN quantity_on_hand = 0 THEN sku_id END) * 100.0
    / NULLIF(COUNT(DISTINCT sku_id), 0) AS stockout_sku_pct
FROM inventory_history
WHERE snapshot_date = CURRENT_DATE - INTERVAL '1 day'
GROUP BY warehouse_id
ORDER BY stockout_sku_pct DESC;

Один склад с stockout 20% — supply chain проблема, а не demand.

Частые ошибки

Ошибка 1. Считать только полную stockout. «Low stock» (1-5 units) → тоже потерянные продажи если demand 10/day.

Ошибка 2. Игнорировать backorders. Backorder — формально stockout, но revenue не теряется (customer ждёт).

Ошибка 3. Считать на slow movers. SKU не продаётся 6 месяцев — его stockout не теряет ничего. Сегментируйте.

Ошибка 4. Lost sales overestimate. Customer может купить substitute, не уходить. Substitution rate — 30-60%.

Ошибка 5. Stockout как single metric. Combine с inventory turnover. Низкий stockout + high turnover = optimal.

Связанные темы

FAQ

Какой stockout норма?

E-com: 2-5%. Retail: 5-10%. Топ-SKU: меньше 1%.

Substitution rate?

30-60% customers купят похожий. Остальные уйдут.

Stockout vs out-of-stock?

Synonym. Out-of-stock — более customer-facing термин.

Safety stock?

Buffer для variance. Стандарт — 2-4 weeks demand.

Cost of stockout?

Lost sales + customer LTV impact + brand damage. Часто 2-3× lost sales monetary.