Собесов

Aafreen29/SQL-Interview-Prep: friend-acceptance rate (Facebook)

SQLАналитика продуктаСредняяMiddle

Условие

В таблице friend_request(sender_id, receiver_id, sent_date) лежат отправленные запросы в друзья. В таблице request_accepted(requester_id, accepter_id, accepted_date) — принятые. Посчитайте общий показатель «доля принятых» — отношение числа принятых уникальных пар (sender → receiver) к числу отправленных. Учтите, что одну и ту же пару можно отправить несколько раз.

Решение

Подход

Сначала сводим запросы к уникальным парам (sender, receiver) через COUNT(DISTINCT ...). То же — для принятых: одна пара = один accept. Считаем отношение.

Реализация

SELECT
    ROUND(
        COALESCE(
            (SELECT COUNT(DISTINCT requester_id || '-' || accepter_id)
             FROM request_accepted)::float
            /
            NULLIF(
                (SELECT COUNT(DISTINCT sender_id || '-' || receiver_id)
                 FROM friend_request), 0
            ),
            0
        )::numeric,
        4
    ) AS acceptance_rate;

Более чистая версия через CTE:

WITH sent AS (
    SELECT DISTINCT sender_id, receiver_id FROM friend_request
),
accepted AS (
    SELECT DISTINCT requester_id, accepter_id FROM request_accepted
)
SELECT
    ROUND(
        (SELECT COUNT(*) FROM accepted)::numeric
        / NULLIF((SELECT COUNT(*) FROM sent), 0),
        4
    ) AS acceptance_rate;

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

  1. Несколько запросов от одной пары. Без DISTINCT посчитаете одну и ту же дружбу 5 раз и завысите знаменатель.
  2. Несовпадение названий колонок: в request_accepted пара называется (requester_id, accepter_id), а не (sender_id, receiver_id). На собеседовании путаются и считают по «не той стороне».
  3. Целочисленное деление. В Postgres/MySQL без приведения к numeric/float получите 0. Всегда ::numeric или * 1.0.
  4. Direction: одна пара (A→B) ≠ (B→A). Если бизнес-смысл «дружба», нужно нормализовать пару: LEAST(a, b), GREATEST(a, b).

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

COUNT(DISTINCT pair) по принятым / COUNT(DISTINCT pair) по отправленным. Защититься от деления на ноль и привести к numeric. Если задача про «дружбу», нормализовать направление пары.

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

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

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