Лада · руководитель агентства «Северный Тракт»
Тестовые ты сдал. Теперь сыграю интервьюера: общий редактор, таймер, три задачи. Мне неважно, сразу ли запрос заработает. Мне важно слышать, что ты проверяешь.
В уроке про карьеру мы разобрали, из каких секций состоит собеседование аналитика. Сегодня репетируем первую и самую предсказуемую: SQL. Её можно натренировать, потому что задачи на ней повторяются из компании в компанию. Ниже порядок решения, восемь классов задач, четыре ошибки под стрессом и три задачи на время.
Как проходит SQL-секция
Интервьюер присылает ссылку на общий редактор и описывает таблицы словами или схемой. Дальше 30-45 минут ты пишешь запросы, а он смотрит, как текст появляется на экране. Это и есть лайвкодинг.
Три особенности, которых нет в тестовом:
- Запуска может не быть. Часто редактор только текстовый, и проверить запрос на базе нельзя. Значит, проверяешь в голове, на маленьком примере.
- Времени мало. Обычно 2-3 задачи, от простой к сложной. Застрять на первой на 20 минут хуже, чем решить её грубо и вернуться.
- Оценивают рассуждение. Интервьюер ставит оценку не за итоговый запрос, а за путь: что уточнил, какие ловушки назвал, как проверил. Молчаливое правильное решение ценится меньше, чем проговорённое решение с одной поправкой.
Поэтому говори вслух всё время. Не «сейчас подумаю» и тишина на минуту, а «у игрока может быть несколько сессий в день, значит дни сначала схлопну через DISTINCT».
Порядок решения: четыре шага
Разберём на задаче, которую любят давать продуктовым аналитикам. Интервьюер говорит: «Сколько игроков заходили в игру 7 дней подряд или больше?»
1. Уточни гранулярность и крайние случаи. Гранулярность отвечает на вопрос «что я считаю»: игроков, а не сессии и не серии. Дальше крайние случаи, по одному вопросу на каждый:
- что такое день: по UTC или по местному времени? Интервьюер: по UTC,
started_at::date; - если у игрока две сессии в один день, это один день серии? Да;
- если у игрока две серии по 8 дней, он считается один раз? Да;
- тестовые аккаунты считаем? Нет.
Каждый ответ сразу превращается в строчку запроса. Без этих вопросов запрос почти наверняка посчитает что-то соседнее.
2. Набросай CTE по шагам. Не пиши всё одним запросом. Каждый шаг это одна CTE с говорящим именем, как в уроке про CTE:
days: одна строка на пару «игрок и день», тесты выкинуты;marked: метка серии, приём из урока про острова. Из дня вычитаем его номер по порядку, и у дней одной серии разность совпадает;series: длина каждой серии;- итог: сколько разных игроков с серией от 7 дней.
SQL-песочница
База · guild
База загрузится, когда ты выполнишь запрос или откроешь таблицы.
Выполни запрос, чтобы увидеть результат.
Выбери доступную таблицу для просмотра данных и структуры.
Выбери доступную таблицу для просмотра данных и структуры.
Выполни весь запрос кнопкой или Ctrl/Cmd+Enter. Ctrl+Space открывает подсказки. Можно писать несколько команд через точку с запятой, менять данные и открывать транзакции. У каждой песочницы своя база, изменения живут до ухода со страницы. «Сбросить базу» возвращает учебные данные, но не меняет SQL.
Ответ: 207 игроков, самая длинная серия 20 дней.
3. Проверь на маленьком примере. Придумай три-четыре строки, на которых видна ловушка, и прогони их в голове или в песочнице. Вот игрок с двумя сессиями 1 июня, одной 2 июня и одной 4 июня, без DISTINCT:
WITH visits(day) AS (
VALUES (date '2026-06-01'), (date '2026-06-01'), (date '2026-06-02'), (date '2026-06-04')
)
SELECT day, day - row_number() OVER (ORDER BY day)::int AS series
FROM visits;
day | series
------------+------------
2026-06-01 | 2026-05-31
2026-06-01 | 2026-05-30
2026-06-02 | 2026-05-30
2026-06-04 | 2026-05-31
Серия 1-2 июня развалилась: второй сеанс 1 июня получил свой номер, и 4 июня попало в одну группу с 1 июня. С DISTINCT дни 1, 2 и 4 июня дают метки 31 мая, 31 мая и 1 июня: серия из двух дней и отдельный день, как и должно быть. На всей базе ошибка заметна: без DISTINCT выходит 397 игроков вместо 207. Скажи интервьюеру, что проверил этот случай.
4. Назови сложность. Одна-две фразы, без формул на доске. Здесь DISTINCT и окно сортируют строки: 38 113 сессий без тестовых аккаунтов схлопываются в 24 721 пару «игрок и день», окно сортирует их внутри каждого игрока. Это один проход с сортировкой, без коррелированных подзапросов, которые выполнялись бы для каждой строки. Если спросят, как ускорить, вспомни урок про индексы: индекс по (player_id, started_at) отдаёт сессии уже упорядоченными.
урок из курса
Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.