Как посчитать First Response Time в SQL
full_name встречаются значения вроде 'Ivan' и 'ivan ' (с пробелом в конце). Нужно надёжно отфильтровать всех пользователей с именем «ivan» независимо от регистра и пробелов по краям. Какое условие подходит лучше всего?Содержание:
Зачем First Response Time
В поддержке FRT — ключевая метрика восприятия сервиса клиентом. Пользователь пишет в чат и ждёт ответ за 10 секунд (чат) или за 4 часа (почта). Если FRT превышен, растёт раздражение.
Формула
FRT = (first_agent_response_time - ticket_created_time)В минутах или часах.
Базовый расчёт
Данные: tickets(ticket_id, user_id, created_at, channel, ...), ticket_messages(ticket_id, sender_type, sent_at).
WITH first_response AS (
SELECT
t.ticket_id,
t.created_at AS ticket_created,
MIN(m.sent_at) FILTER (WHERE m.sender_type = 'agent') AS first_agent_response
FROM tickets t
LEFT JOIN ticket_messages m ON m.ticket_id = t.ticket_id
WHERE t.created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY t.ticket_id, t.created_at
)
SELECT
AVG(EXTRACT(EPOCH FROM (first_agent_response - ticket_created)) / 60) AS avg_frt_minutes,
PERCENTILE_CONT(0.5) WITHIN GROUP (
ORDER BY EXTRACT(EPOCH FROM (first_agent_response - ticket_created)) / 60
) AS median_frt_minutes,
PERCENTILE_CONT(0.9) WITHIN GROUP (
ORDER BY EXTRACT(EPOCH FROM (first_agent_response - ticket_created)) / 60
) AS p90_frt_minutes
FROM first_response
WHERE first_agent_response IS NOT NULL;Соблюдение SLA
Допустим, SLA такой: чат — 5 минут, почта — 4 часа.
WITH frt AS (
SELECT
t.ticket_id,
t.channel,
EXTRACT(EPOCH FROM (MIN(m.sent_at) FILTER (WHERE m.sender_type = 'agent') - t.created_at)) / 60 AS frt_min
FROM tickets t
LEFT JOIN ticket_messages m ON m.ticket_id = t.ticket_id
GROUP BY t.ticket_id, t.channel, t.created_at
)
SELECT
channel,
COUNT(*) AS tickets,
COUNT(*) FILTER (WHERE
(channel = 'chat' AND frt_min <= 5)
OR (channel = 'email' AND frt_min <= 240)
)::NUMERIC * 100 / NULLIF(COUNT(*), 0) AS sla_compliance_pct
FROM frt
WHERE frt_min IS NOT NULL
GROUP BY channel;По каналам
SELECT
channel,
COUNT(*) AS tickets,
AVG(frt_min) AS avg_frt_min,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY frt_min) AS median_frt_min
FROM frt
WHERE frt_min IS NOT NULL
GROUP BY channel
ORDER BY avg_frt_min;Чат обычно 1-5 минут. Почта — 1-8 часов. Телефон — мгновенно (или пропущенный звонок).
Частые ошибки
Ошибка 1. Не учитывать нерабочее время. Тикет пришёл в 22:00 (вне рабочего времени), первый ответ — на следующий день в 9:00, и FRT получается 11 часов. Это несправедливо по сравнению с метрикой, посчитанной только по рабочим часам.
Ошибка 2. Считать автоответы за ответ. «Мы получили ваш тикет» — это автоответ, а не ответ живого агента. Фильтруйте по sender_type = 'agent' (настоящий агент).
Ошибка 3. Переоткрытие тикетов. Пользователь переоткрыл тикет. FRT для переоткрытия — это отдельная метрика.
Ошибка 4. Среднее на скошенных данных. Несколько крайних выбросов (очень долгий FRT) перетягивают среднее на себя. Берите медиану и перцентили.
Ошибка 5. Часовые пояса. Тикеты хранятся в UTC, а поддержка работает по местному времени. Приводите время к одному поясу.
Связанные темы
- Как посчитать CSAT в SQL
- Как посчитать CES в SQL
- Как посчитать NPS в SQL
- Как посчитать time to resolution в SQL
FAQ
Какой FRT считается нормальным?
Для чата нормой считаются 1-5 минут, для почты — 1-4 часа, для телефона — мгновенный ответ. Конкретная планка зависит от того, чего ждёт ваша аудитория.
Считать FRT по рабочим часам?
Да, так сравнение получается честным. Считайте FRT только в пределах рабочего времени, иначе ночные тикеты испортят метрику.
Автоответы считать?
Нет, автоответы в FRT не учитывают. Берите только ответы живых агентов.
FRT или Time to Resolution?
FRT — это время до первого ответа, а Time to Resolution — время до полного закрытия тикета. Первая метрика про скорость реакции, вторая — про скорость решения проблемы.
FRT высокий — что делать?
Есть несколько рычагов: увеличить штат агентов, улучшить самообслуживание, оптимизировать маршрутизацию тикетов и доработать базу знаний. Обычно комбинация из двух-трёх даёт заметный эффект.