Программы
Подготовка к собеседованиямA/B-тесты для аналитиковML и Causal InferenceA/B-тесты для менеджеровОбучение для команд
Бесплатные материалы
База знаний185+ тестовых заданийRoadmap по A/BЧеклист A/B-тестаОтзывыО проектеОставить заявку
Собеседования и тестовые задания

Разбор тестового задания на SQL в EdTech-компании

1 апреля 2025·4 мин чтения·Павел Бухтик·Оригинал в Telegram ↗

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

Предлагаю потренироваться на задачах с тестового задания на SQL.

Дано две таблицы.

Первая — finished_lessons, в ней лежит информация о пройденных уроках:

ПолеОписание поляТип
user_idid пользователяinteger
lesson_idid урокаinteger
date_createdдата создания записи / дата прохождения урокаdate

Вторая — profession_dop, в ней лежит информация о подписках пользователей на профессии:

ПолеОписание поляТип
profession_nameназвание профессииstring
user_idid пользователяinteger
subscription_dateдата подпискиdate
squadпотокstring

Разберем несколько SQL-запросов по этим таблицам.


1. Необходимо посмотреть, какое количество пользователей находятся в потоке 17 по профессии data-analyst

Простой запрос из одной таблицы. Фильтруем profession_dop по потоку 17 и профессии data-analyst, затем считаем количество пользователей:

sql
SELECT    COUNT(DISTINCT user_id) AS usersFROM profession_dopWHERE profession_name = 'data-analyst'    AND squad = '17';

2. Необходимо посмотреть, какое количество пользователей по профессии data-scientist подписались в 2020 году

Тоже довольно прямолинейный запрос. Используем функцию YEAR() для извлечения года из даты подписки и фильтруем по 2020 году:

sql
SELECT    COUNT(DISTINCT user_id) AS usersFROM profession_dopWHERE profession_name = 'data-scientist'    AND YEAR(subscription_date) = 2020;

3. Необходимо найти, какое количество уроков прошли студенты по профессии project-manager

Для решения этой задачи подойдет и подзапрос user_id IN (SELECT …), и JOIN двух таблиц.

Предлагаемый ниже запрос обеспечивает лучшую читаемость и производительность за счет CTE:

sql
WITH project_managers AS (    SELECT DISTINCT user_id    FROM profession_dop    WHERE profession_name = 'project-manager')SELECT    COUNT(DISTINCT lesson_id) AS lessonsFROM finished_lessonsINNER JOIN project_managers USING(user_id);

4. Необходимо найти первый пройденный урок (lesson_id) для пользователей, подписавшихся на профессию qa в марте 2020 года

Здесь я бы в первую очередь уточнял задачу у интервьюера, т.к. она может трактоваться по-разному:

1. Найти самый первый урок за все время для каждого пользователя из подписавшихся на профессию qa в марте 2020 года.

2. Найти первый урок по qa для каждого пользователя из подписавшихся на профессию qa в марте 2020 года.

Решение первого варианта восприятия:

sql
WITH qa_users AS (    SELECT DISTINCT user_id    FROM profession_dop    WHERE profession_name = 'qa'        AND YEAR(subscription_date) = 2020        AND MONTH(subscription_date) = 3),first_lesson_date AS (    SELECT         fl.user_id,        MIN(fl.date_created) AS first_lesson_date    FROM finished_lessons fl    INNER JOIN qa_users USING(user_id)    GROUP BY fl.user_id)SELECT    fl.user_id,    fl.lesson_idFROM finished_lessons AS flINNER JOIN first_lesson_date AS fld    ON fl.user_id = fld.user_id    AND fl.date_created = fld.first_lesson_date;

Решение второго варианта можете предложить в комментариях.


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

Используем оконную функцию DENSE_RANK() для ранжирования профессий по количеству студентов, затем выбираем топ-5.

Способ формирования топа лучше уточнять. В моем случае, если какая-то профессия делит с кем-то место — хотим видеть все и считать за одно место:

sql
WITH profession_counts AS (    SELECT        profession_name,        COUNT(DISTINCT user_id) AS student_count,        DENSE_RANK() OVER (            ORDER BY COUNT(DISTINCT user_id) DESC        ) AS rank    FROM profession_dop    GROUP BY profession_name)SELECT     profession_name,     student_countFROM profession_countsWHERE rank <= 5;

6. Необходимо вывести уроки и даты их прохождения по пользователю 145768, отсортировав от первого пройденного урока к последнему, по профессии project-manager

Вообще кажется, что в БД должно быть больше полей. Для решения этой задачи таблица profession_dop должна содержать поле с id курса — profession_id. А база с уроками должна содержать id профессии, в которой был выполнен урок. Либо должна быть третья таблица для маппинга профессий и id уроков у них.

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

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

sql
WITH project_manager_user AS (    SELECT        user_id,        subscription_date    FROM profession_dop    WHERE profession_name = 'project-manager'        AND user_id = 145768)SELECT    fl.lesson_id,    fl.date_createdFROM finished_lessons flINNER JOIN project_manager_user USING(user_id)WHERE date_created >= subscription_dateORDER BY fl.date_created ASC;

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

Иногда правильный ответ – это не просто код, а уточнение бизнес-логики и объяснение, почему задача в текущем виде решается неоднозначно.

Готовишься к собеседованию на аналитика?

Посмотри базу реальных тестовых заданий и разборы кейсов.

Перейти к тестовым заданиям