Собесов

Glassdoor (Meta) — Acceptance Rate friend-request по месяцам

SQLTime-aware ratioСредняяMiddle

Условие

Таблицы:

  • friend_requests(sender_id, receiver_id, sent_date)
  • friend_accepts(sender_id, receiver_id, accepted_date)

Для каждого месяца отправки верните acceptance rate: доля заявок, принятых в принципе (когда-либо), относительно отправленных в этот месяц.

Решение

WITH sent AS (
  SELECT
    DATE_TRUNC('month', sent_date)::DATE AS month,
    sender_id, receiver_id
  FROM friend_requests
),
joined AS (
  SELECT
    s.month,
    s.sender_id, s.receiver_id,
    CASE WHEN a.accepted_date IS NOT NULL THEN 1 ELSE 0 END AS accepted
  FROM sent s
  LEFT JOIN friend_accepts a
    ON a.sender_id   = s.sender_id
   AND a.receiver_id = s.receiver_id
)
SELECT
  month,
  ROUND(AVG(accepted)::NUMERIC, 4) AS acceptance_rate
FROM joined
GROUP BY month
ORDER BY month;

Тонкость с «когда-либо принято»

LEFT JOIN без фильтра по accepted_date — у заявки от мая 2024 может быть accept в июне 2025. Это всё ещё «принято». Если же хотим «принято в течение N дней» — нужен дополнительный фильтр в ON.

Дубли

Если на одну пару (sender, receiver) пришло несколько accepts (например, после повторной отправки) — LEFT JOIN задвоит. Защита:

LEFT JOIN (SELECT DISTINCT sender_id, receiver_id FROM friend_accepts) a
  ON ...

или EXISTS:

SELECT
  DATE_TRUNC('month', sent_date)::DATE AS month,
  ROUND(
    AVG(CASE WHEN EXISTS (
      SELECT 1 FROM friend_accepts a
      WHERE a.sender_id = r.sender_id AND a.receiver_id = r.receiver_id
    ) THEN 1.0 ELSE 0 END), 4
  ) AS acceptance_rate
FROM friend_requests r
GROUP BY 1
ORDER BY 1;

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

  1. Перепутать sender/receiver. В оригинале одного направления: (sender, receiver) — accept должен быть тот же ключ.
  2. LEFT JOIN без DISTINCT в правой. Задвоение accept-ов искажает знаменатель/числитель.
  3. Заявки без accept остаются. Это правильно — они в знаменателе, но не в числителе.
  4. NULL acceptance. В первый месяц со 100% непринятыми — AVG = 0, не NULL. С пустыми месяцами — 0/0 отсутствует.

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

LEFT JOIN или EXISTS, AVG(accepted) по месяцу отправки. С защитой от дублей в accepts.

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

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

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