Собесов

Билайн Junior — динамика маржи по неделям и сравнение Сайта и Приложения

SQLMargin / channel comparisonЛёгкаяJunior

Условие

Дана таблица t_orders(organization_id, sales_order, date_create, status, code, client_id, tvz_id, cost_price, price_b2b_gross, price_b2c_gross, quantity).

Особенности:

  • sales_order начинается на 2051 — Сайт, на 2061 — Приложение.
  • status = 0 — Выдан, остальные — Отменён.

Задачи:

  1. Динамика маржи по неделям (запрос + диаграмма + лучшая неделя).
  2. Маржа в рублях и % по всей компании за август, в разрезе Сайта и Приложения. Вывод:
Сайт Приложение
Маржа руб
Маржа %
  1. Логика (без SQL): 70% клиентов любят бонусы, 80% — промокоды. Найти % любящих и то, и другое.

Решение

1. Маржа по неделям

Маржа = price_b2c_gross - cost_price. Берём только выданные (status = 0):

WITH wk AS (
  SELECT DATE_TRUNC('week', date_create) AS wk_start,
         SUM((price_b2c_gross - cost_price) * quantity) AS margin_rub,
         SUM(price_b2c_gross * quantity)                AS revenue_rub
  FROM t_orders
  WHERE status = 0
  GROUP BY DATE_TRUNC('week', date_create)
)
SELECT wk_start, margin_rub, revenue_rub,
       margin_rub * 100.0 / NULLIF(revenue_rub, 0) AS margin_pct
FROM wk
ORDER BY wk_start;

Лучшая неделя:

SELECT wk_start, margin_rub
FROM (... выше ...) wk
ORDER BY margin_rub DESC LIMIT 1;

2. Маржа за август по каналам

SELECT
  CASE WHEN sales_order::text LIKE '2051%' THEN 'Сайт'
       WHEN sales_order::text LIKE '2061%' THEN 'Приложение'
       ELSE 'Other' END                                          AS channel,
  SUM((price_b2c_gross - cost_price) * quantity)                  AS margin_rub,
  SUM((price_b2c_gross - cost_price) * quantity) * 100.0
   / NULLIF(SUM(price_b2c_gross * quantity), 0)                   AS margin_pct
FROM t_orders
WHERE status = 0
  AND date_create >= DATE '2022-08-01'
  AND date_create <  DATE '2022-09-01'
GROUP BY 1;

Pivot ручной:

SELECT
  'Маржа руб'   AS metric,
  SUM(CASE WHEN sales_order::text LIKE '2051%' THEN (price_b2c_gross - cost_price) * quantity ELSE 0 END) AS site,
  SUM(CASE WHEN sales_order::text LIKE '2061%' THEN (price_b2c_gross - cost_price) * quantity ELSE 0 END) AS app
FROM t_orders
WHERE status = 0 AND date_create >= '2022-08-01' AND date_create < '2022-09-01'
UNION ALL
SELECT
  'Маржа %',
  SUM(CASE WHEN sales_order::text LIKE '2051%' THEN (price_b2c_gross - cost_price) * quantity ELSE 0 END) * 100.0
   / NULLIF(SUM(CASE WHEN sales_order::text LIKE '2051%' THEN price_b2c_gross * quantity ELSE 0 END), 0),
  SUM(CASE WHEN sales_order::text LIKE '2061%' THEN (price_b2c_gross - cost_price) * quantity ELSE 0 END) * 100.0
   / NULLIF(SUM(CASE WHEN sales_order::text LIKE '2061%' THEN price_b2c_gross * quantity ELSE 0 END), 0)
FROM t_orders
WHERE status = 0 AND date_create >= '2022-08-01' AND date_create < '2022-09-01';

3. Бонусы ∧ Промокоды

Без доп. данных: P(A ∧ B) ∈ [P(A) + P(B) − 1, min(P(A), P(B))] = [50%, 70%].

Если независимы: P(A ∧ B) = 0.7 × 0.8 = 56%.

Корректный ответ: «В диапазоне 50–70%, точно — нужно знать корреляцию. Если независимо — 56%.»

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

  1. price_b2c_gross = 0.00 в данных — нужен ли учёт? Возможно, цены в другой колонке. Уточняйте.
  2. Quantity отрицательное (возврат): (b2c - cost) × qty корректно отразит минус.
  3. status = 0 Выдан vs остальные — не путайте с булевым.
  4. sales_order int vs text: в условии — int. Но LIKE '2051%' — на text. Cast обязателен.
  5. «Маржа %»: маржа делится на цену продажи, а не себестоимости — это margin% (gross profit margin), не markup%.
  6. Лучшая неделя: по абсолютной марже или относительной (margin %)? — уточняйте.

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

(1) Group by week → SUM(margin) → диаграмма; лучшая неделя — ORDER BY DESC LIMIT 1. (2) CASE для channel + sums + перевод в %. (3) Без независимости — диапазон [50%, 70%].

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

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

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