Собесов

Сбермаркет SQL — CSI по дням и каналам обращения

SQLRatio-метрикиСредняяMiddle

Условие

Витрина обращений request_agg:

  • dt — дата.
  • type_appeal — клиентский / партнёрский.
  • direction — голос / чаты / заявки партнёра / исход / поддержка ритейлеров.
  • theme, subtheme — тема и подтема.
  • assembly_type, type_store_delivery — тип сборки и доставки.
  • total_bid — кол-во обращений.
  • numerator_csi — числитель для CSI (сумма «положительных» оценок).
  • total_rates — знаменатель CSI (всего оценок).

Посчитать CSI по дням и каналам (direction) только для клиентских обращений. Считать только дни с достаточным числом оценок (фильтр шума).

Решение

Что такое CSI

CSI = numerator_csi / total_rates. В витрине уже агрегировано — нужно правильно сложить числитель и знаменатель отдельно, а не усреднить готовый CSI (это ошибка ratio-метрик).

Реализация

WITH agg AS (
  SELECT
    dt,
    direction,
    SUM(numerator_csi)::numeric AS num_sum,
    SUM(total_rates)::numeric   AS den_sum,
    SUM(total_bid)              AS bids_sum
  FROM request_agg
  WHERE type_appeal = 'Клиентский'
  GROUP BY dt, direction
)
SELECT
  dt,
  direction,
  bids_sum,
  den_sum                                   AS rates_sum,
  CASE WHEN den_sum >= 30
       THEN ROUND(num_sum / den_sum, 3)
       ELSE NULL  -- мало оценок - неустойчивая метрика
  END                                       AS csi
FROM agg
ORDER BY dt, direction;

Почему «усреднять CSI» неправильно

Если CSI в день А считался по 1000 оценок (=0.5), а в день В — по 10 оценок (=0.9), их арифметическое среднее 0.7 ничего не значит. Правильно — сложить числитель (500+9=509) и знаменатель (1010), получить 0.504.

Это общее правило для всех ratio-метрик: CTR, CR, ROAS, NPS — никогда не усредняем готовое отношение.

Альтернатива — взвешенное среднее

SELECT direction,
       SUM(numerator_csi) / NULLIF(SUM(total_rates), 0) AS csi_overall
FROM request_agg
WHERE type_appeal='Клиентский'
GROUP BY direction;

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

  1. numerator_csi может быть отрицательным в данных (если шкала включает -1 или штрафные оценки). В этой витрине так и есть: видны строки с numerator_csi = -2. Учитывать, что CSI ∈ [-1; 1].
  2. total_rates < total_bid — норма: не все обращения получают оценку. Считаем CSI только по total_rates.
  3. «Достаточное число оценок». Без порога CSI 1.0 при 1 оценке — мусор. Минимум 30 — эмпирический; в проде — биномиальный CI с lower bound (Wilson score) для рейтинга.
  4. Партнёрские обращения. В request_agg есть оба типа; фильтр type_appeal = 'Клиентский' обязателен.
  5. assembly_type/type_store_delivery бывают NULL — не дублируем строки, но и не выкидываем.
  6. Деление на 0. NULLIF(den_sum, 0) — must.

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

SUM(numerator_csi) / NULLIF(SUM(total_rates), 0) по (dt, direction) для клиентских обращений, с порогом по SUM(total_rates) ≥ 30. Никогда не усреднять готовое отношение по строкам — это типовая ошибка ratio-метрик.

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

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

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