Условие
Дана таблица 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— Выдан, остальные — Отменён.
Задачи:
- Динамика маржи по неделям (запрос + диаграмма + лучшая неделя).
- Маржа в рублях и % по всей компании за август, в разрезе Сайта и Приложения. Вывод:
| Сайт | Приложение | |
|---|---|---|
| Маржа руб | ||
| Маржа % |
- Логика (без 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%.»
Подводные камни
price_b2c_gross = 0.00в данных — нужен ли учёт? Возможно, цены в другой колонке. Уточняйте.- Quantity отрицательное (возврат):
(b2c - cost) × qtyкорректно отразит минус. status = 0Выдан vs остальные — не путайте с булевым.sales_orderint vs text: в условии — int. НоLIKE '2051%'— на text. Cast обязателен.- «Маржа %»: маржа делится на цену продажи, а не себестоимости — это margin% (gross profit margin), не markup%.
- Лучшая неделя: по абсолютной марже или относительной (margin %)? — уточняйте.
Эталонный ответ
(1) Group by week → SUM(margin) → диаграмма; лучшая неделя — ORDER BY DESC LIMIT 1. (2) CASE для channel + sums + перевод в %. (3) Без независимости — диапазон [50%, 70%].