Главная / База знаний / Мышление на техсобеседовании
Лайвкодинг & Собеседования

Как на техсобеседовании по SQL показать мышление, а не просто код: разбор от тимлида

Как человек, который регулярно проводит технические собеседования в финтехе и отсматривает десятки решений на лайвкодинге, открою вам главный секрет: на технических собеседованиях почти никогда не смотрят только на голый код.

Смотрят прежде всего на то, КАК вы думаете.

И самый очевидный, сильный маркер живого аналитического мышления — это вопросы.

Почему нельзя сразу бросаться писать код

Типичная ошибка кандидатов: интервьюер открывает пустой редактор и озвучивает условие задачи (например: «Посчитай отток клиентов за прошлый месяц»). Кандидат бледнеет, замолкает и судорожно начинает строчить в редакторе `SELECT user_id, ...`.

Когда вам дают задачу, её не обязательно и даже вредно решать с первой секунды. Нормально — и даже критически важно — сначала уточнить:

Для меня как нанимающего лида такой диалог — это моментальный зелёный флаг. Это сигнал, что передо мной осознанный специалист, который в реальной работе не зальет в прод неверную витрину из-за недопонимания ТЗ.

Техника «Мышление вслух»: как заставить интервьюера вам помогать

Перед тем как написать хоть одну строчку SQL, проговорите свой подход вслух:

«Смотрите: сначала мне нужно отфильтровать отмененные платежи. Затем, скорее всего, понадобится оконная функция с PARTITION BY по клиенту, чтобы найти дату предыдущего входа. А в основном запросе я сделаю разницу между датами через DATEDIFF и отберу тех, у кого интервал превысил 30 дней.»

Это не должно быть идеальным синтаксисом. Это просто ход вашей мысли.

Когда вы комментируете свои шаги по ходу решения, интервьюер понимает, куда вы движетесь. И если видит, что направление верное, но вы опечатались в синтаксисе — он сам с улыбкой подскажет: «Посмотри на условие в оконном фрейме».

А вот когда человек молчит 10 минут, пишет сложный запрос и в итоге выдает неверный результат — помогать уже невозможно. Не потому что интервьюер злой, а потому что совершенно непонятно, как кандидат думал.

Telegram @itindata Разборы реальных тестовых заданий и инсайты собеседований в бигфинтех.
Подписаться на @itindata

Разбор боевых задач: как демонстрировать мышление на практике

Задача 1. Дедупликация записей и поиск последней транзакции

Условие: В таблице `payments` хранятся логи платежей. Из-за сетевых сбоев некоторые транзакции залогировались дважды. Нужно вывести только самый последний статус для каждого `order_id`.

Как рассуждать вслух: «Обычный GROUP BY по order_id с MAX(created_at) не вернет мне остальные атрибуты платежа без дополнительного джойна. Поэтому я использую оконную функцию ROW_NUMBER() с группировкой по order_id и сортировкой по created_at DESC. Затем заверну это в CTE и отфильтрую rn = 1.»

PostgreSQL / ClickHouseSQL
WITH ranked_payments AS (
    SELECT 
        order_id,
        user_id,
        amount,
        status,
        created_at,
        ROW_NUMBER() OVER (
            PARTITION BY order_id 
            ORDER BY created_at DESC
        ) AS rn
    FROM payments
)
SELECT 
    order_id,
    user_id,
    amount,
    status,
    created_at
FROM ranked_payments
WHERE rn = 1;

Задача 2. Топ-3 товара в каждой категории (RANK vs DENSE_RANK)

Условие: Найти 3 самых прибыльных товара в каждой категории каталога.

Вопрос интервьюеру: «Как мы поступаем, если у 3-го и 4-го товаров абсолютно одинаковая выручка? Должны ли мы включить оба товара (DENSE_RANK) или строго ограничить тремя строками (ROW_NUMBER)?»

PostgreSQLSQL
WITH ranked_products AS (
    SELECT 
        category_id,
        product_id,
        revenue,
        DENSE_RANK() OVER (
            PARTITION BY category_id 
            ORDER BY revenue DESC
        ) AS rnk
    FROM product_sales
)
SELECT 
    category_id,
    product_id,
    revenue,
    rnk
FROM ranked_products
WHERE rnk <= 3
ORDER BY category_id, rnk;

Задача 3. Расчет темпа роста выручки Month-over-Month (MoM)

Условие: Рассчитать помесячную выручку и процент её изменения относительно предыдущего месяца.

Как рассуждать вслух: «Сначала агрегируем выручку помесячно с помощью DATE_TRUNC. Затем используем LAG(), чтобы достать значение предыдущего месяца. При расчете процента прироста обязательно добавим проверку на деление на ноль или NULL для самого первого месяца в истории.»

PostgreSQLSQL
WITH monthly_revenue AS (
    SELECT 
        DATE_TRUNC('month', payment_date) AS month,
        SUM(amount) AS current_revenue
    FROM transactions
    WHERE status = 'SUCCESS'
    GROUP BY 1
),
with_lag AS (
    SELECT 
        month,
        current_revenue,
        LAG(current_revenue) OVER (ORDER BY month) AS prev_revenue
    FROM monthly_revenue
)
SELECT 
    month,
    current_revenue,
    prev_revenue,
    ROUND(
        (current_revenue - prev_revenue)::NUMERIC / NULLIF(prev_revenue, 0) * 100, 
        2
    ) AS mom_growth_pct
FROM with_lag
ORDER BY month;

Задача 4. Пользователи с непрерывной активностью 3 дня подряд (Gaps & Islands)

Условие: Найти клиентов, заходивших в банковское приложение минимум 3 дня подряд без перерывов.

Как рассуждать вслух: «Это классический паттерн Gaps & Islands ("Острова и пропуски"). Если вычесть порядковый номер дня ROW_NUMBER() из календарной даты активности, то для непрерывной серии дней эта разница останется константой. Это позволит сгруппировать дни в непрерывные интервалы.»

PostgreSQLSQL
WITH distinct_days AS (
    -- Убираем повторные заходы в течение одних суток
    SELECT DISTINCT 
        user_id, 
        login_time::DATE AS login_date
    FROM user_logins
),
numbered_logins AS (
    SELECT 
        user_id,
        login_date,
        login_date - (ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) * INTERVAL '1 day') AS grp
    FROM distinct_days
)
SELECT 
    user_id,
    MIN(login_date) AS streak_start,
    MAX(login_date) AS streak_end,
    COUNT(*) AS consecutive_days
FROM numbered_logins
GROUP BY user_id, grp
HAVING COUNT(*) >= 3;
Главное правило интервьюера

Мышление — это не скорость печати и не заучивание наизусть сотен функций. Это способность задать точный вопрос, объяснить логику и разложить сложную задачу на прозрачные шаги.

На индивидуальных занятиях в программе подготовки к собеседованиям мы отрабатываем именно этот навык: моделируем живой лайвкодинг, тренируем мышление вслух и доводим решение типовых финтех-задач до автоматизма.

Готовитесь к техсобеседованиям в топовые компании?

Проведем тренировочное собеседование, разберем ваши слепые зоны и выстроим сильное позиционирование. Оплата менторства — только после получения заветного оффера.

Пройти мок-интервью с Анатолием (@itindata)