Вопросы на собеседовании Data Analyst: 39 вопросов с ответами и задачи по SQL
На собеседовании Junior Data Analyst проверяют четыре вещи: умеете ли вы достать данные запросом SQL, понимаете ли базовую статистику, можете ли собрать отчёт в таблицах или BI-инструменте и способны ли объяснить цифру человеку из бизнеса. В статье — 39 вопросов с короткими ответами, сгруппированных по семи темам: SQL, статистика, Excel, Power BI, pandas, продуктовые метрики и коммуникация. Самый большой блок — SQL, с запросами и их реальным результатом. После вопросов — четыре практические задачи с решениями, типичные ошибки и план подготовки на две недели.
Я тренер Prog Academy по Power BI и преподаватель высшей школы, поэтому вижу подготовку к собеседованиям со стороны студентов. Чаще всего подводит не забытая функция, а неумение объяснить, почему цифра получилась именно такой: откуда взялись строки, что стало с пустыми значениями, почему итог не сходится с соседним отчётом. Ответы ниже построены так, чтобы вы могли произнести их вслух, а затем показать на примере.
Все SQL-запросы выполнены в SQLite 3.51, результаты в статье — реальный вывод. Там, где синтаксис или поведение в PostgreSQL и MySQL отличается, это указано рядом с запросом. Примеры pandas запущены на pandas 2.3. Формулы DAX — стандартные меры из документации Microsoft; запустить их вне Power BI нельзя, поэтому они приведены без вывода. Подбор вопросов — авторский, на основе преподавательского опыта, а не статистика по собеседованиям.
Как проходит собеседование на Data Analyst?
Обычно отбор состоит из четырёх этапов: скрининг с рекрутером, техническое интервью, практическое задание и финальная встреча с руководителем или командой. Порядок и количество этапов у компаний разные: где-то задание дают до технического интервью, где-то два этапа объединяют в один созвон. Чем занимается аналитик в работе, разобрано в статье профессия аналитик данных.
| Этап | Что проверяют | Как готовиться |
|---|---|---|
| Скрининг с рекрутером | Мотивацию, опыт и проекты, ожидания по формату и оплате, уровень английского | Рассказ о себе на две минуты, один проект в формате «задача — данные — что сделал — результат», вилка ожиданий |
| Техническое интервью | SQL, статистику, инструменты из вакансии, понимание метрик | Вопросы из этой статьи: проговорить ответы вслух и написать запросы руками |
| Практическое задание | Умение дойти от сырых данных до вывода: live-coding по SQL или домашнее задание с набором данных | Задачи из раздела «Практические задачи»; привычка сначала проверять данные, потом считать |
| Финальная встреча | Как вы общаетесь, задаёте вопросы и реагируете на неясную постановку задачи | Подготовить вопросы к команде и пример ситуации, когда вы уточняли задачу или защищали вывод |
О зарплатах на собеседовании спрашивают уже на первом этапе. Цифры здесь не приводим, чтобы не устаревали: медианные зарплаты по уровням собраны на странице зарплаты Data Analyst.
Какие темы спрашивают у Junior и Middle?
От Junior ждут уверенного SQL, базовой статистики и одного инструмента отчётности; от Middle — тех же тем глубже, плюс самостоятельности в постановке задачи. Таблица показывает, что именно проверяют в каждой теме. Уровни указаны по опыту автора, без частот: набор тем в конкретной компании определяет вакансия.
| Тема | Что проверяют | Уровень |
|---|---|---|
| SQL: SELECT, WHERE, JOIN, GROUP BY | Написать запрос к двум-трём таблицам и объяснить, сколько строк он вернёт | Junior |
| SQL: подзапросы, CTE, NULL, дубликаты | Разбить задачу на шаги, не потерять и не размножить строки | Junior |
| SQL: оконные функции | Ранжирование, накопительный итог, сравнение с предыдущим периодом | Junior — основы, Middle — уверенно |
| Статистика | Среднее и медиана, разброс, корреляция, смысл p-value | Junior |
| A/B-тесты | Дизайн эксперимента, размер выборки, интерпретация результата | Junior — принцип, Middle — дизайн |
| Excel / Google Sheets | Функции поиска, сводные таблицы, очистка данных | Junior |
| Power BI и визуализация | Модель данных, связи, меры, выбор диаграммы | Junior |
| DAX: CALCULATE и контексты | Объяснить, почему мера возвращает именно это число | Junior — основы, Middle — уверенно |
| Python и pandas | Чтение, фильтрация, группировка, объединение, пропуски | Junior, если указано в вакансии |
| Метрики продукта | Конверсия, удержание, когорты, LTV, расследование падения метрики | Junior — определения, Middle — расследование |
| Коммуникация | Объяснить вывод без терминов, уточнить нечёткую задачу | Junior и Middle |
Вопросы по SQL
SQL — главный блок технического интервью аналитика: проверяют JOIN, агрегацию, NULL и оконные функции. Все примеры ниже работают с двумя таблицами: клиенты и заказы. Создайте их у себя и запускайте запросы по ходу чтения — в SQL понимание приходит через руки. Если вы начинаете с нуля, сначала прочитайте SQL для начинающих.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
city TEXT,
signup_date TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER REFERENCES customers(id),
order_date TEXT NOT NULL,
amount INTEGER,
status TEXT NOT NULL
);
INSERT INTO customers VALUES
(1, 'Olena', 'Kyiv', '2026-01-10'),
(2, 'Taras', 'Lviv', '2026-01-25'),
(3, 'Iryna', 'Kyiv', '2026-02-03'),
(4, 'Maksym', NULL, '2026-02-14'),
(5, 'Sofiia', 'Odesa', '2026-03-01');
INSERT INTO orders VALUES
(1, 1, '2026-01-12', 1200, 'paid'),
(2, 1, '2026-02-05', 800, 'paid'),
(3, 2, '2026-01-28', 450, 'paid'),
(4, 2, '2026-02-05', 450, 'refunded'),
(5, 3, '2026-02-10', 2000, 'paid'),
(6, 3, '2026-03-02', 1200, 'paid'),
(7, 4, '2026-03-15', NULL, 'pending'),
(8, 1, '2026-03-20', 800, 'paid'),
(9, 3, '2026-03-28', 300, 'paid');
В данных специально есть неудобные места: клиент без города, клиент без заказов, заказ без суммы и два заказа в один день. Именно на таких строках строятся вопросы интервью. В SQLite даты хранятся как текст в формате ISO; в PostgreSQL и MySQL для этих столбцов используйте тип DATE.
В каком порядке выполняется запрос SELECT?
Логический порядок такой: FROM и JOIN, затем WHERE, GROUP BY, HAVING, оконные функции, SELECT, DISTINCT, ORDER BY и в конце LIMIT. Пишем мы запрос в одном порядке, а выполняется он в другом.
Из этого порядка следуют три практических правила. В WHERE нельзя использовать агрегатную функцию — группы ещё не собраны. В WHERE нельзя использовать оконную функцию — её результат фильтруют во внешнем запросе или CTE. А псевдоним столбца из SELECT надёжно доступен только в ORDER BY: в WHERE и HAVING PostgreSQL его не примет, хотя SQLite и MySQL в HAVING принимают. Поэтому в переносимом запросе выражение повторяют.
Что хотят услышать: не заученный список, а вывод из него — почему условие на сумму группы пишут в HAVING.
Чем WHERE отличается от HAVING?
WHERE отбирает строки до группировки, HAVING — группы после неё. Поэтому условие на отдельную строку пишут в WHERE, а условие на результат агрегатной функции — в HAVING.
SELECT customer_id,
COUNT(*) AS orders_cnt,
SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY customer_id
HAVING SUM(amount) > 1000
ORDER BY revenue DESC;
customer_id orders_cnt revenue
----------- ---------- -------
3 3 3500
1 3 2800
Сначала WHERE убрал возврат и неоплаченный заказ, затем строки сгруппировались по клиенту, и только потом HAVING отбросил клиента 2 с выручкой 450. В HAVING повторено выражение SUM(amount), а не псевдоним revenue: так запрос работает и в PostgreSQL.
Какие бывают JOIN и чем INNER JOIN отличается от LEFT JOIN?
INNER JOIN возвращает только те строки, для которых нашлась пара в обеих таблицах. LEFT JOIN возвращает все строки левой таблицы, а там, где пары справа нет, подставляет NULL. Ещё есть RIGHT JOIN (зеркало левого), FULL OUTER JOIN (все строки обеих таблиц) и CROSS JOIN (каждая с каждой).
SELECT c.name, COUNT(o.id) AS orders_cnt
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY c.id;
name orders_cnt
------ ----------
Olena 3
Taras 2
Iryna 3
Maksym 1
Sofiia 0
С INNER JOIN Sofiia из результата исчезла бы: у неё нет заказов. Обратите внимание на COUNT(o.id): COUNT(*) вернул бы для неё 1, потому что строка с пустой правой частью всё равно существует. FULL OUTER JOIN есть в PostgreSQL и в SQLite начиная с версии 3.39, в MySQL его нет.
Почему LEFT JOIN иногда ведёт себя как INNER JOIN?
Потому что условие на правую таблицу стоит в WHERE. У строк без пары столбцы правой таблицы равны NULL, сравнение NULL = 'paid' не даёт истину, и WHERE такие строки отбрасывает. Чтобы сохранить все строки слева, условие переносят в ON.
SELECT c.name, COUNT(o.id) AS paid_orders
FROM customers AS c
LEFT JOIN orders AS o
ON o.customer_id = c.id AND o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY c.id;
name paid_orders
------ -----------
Olena 3
Taras 1
Iryna 3
Maksym 0
Sofiia 0
Тот же запрос с WHERE o.status = 'paid' вместо условия в ON возвращает три строки: Maksym и Sofiia пропадают. Типичная ошибка: отчёт «клиенты и их оплаченные заказы» молча теряет клиентов без оплат, и это никто не замечает.
Как найти клиентов, у которых нет ни одного заказа?
Два стандартных способа: LEFT JOIN с проверкой IS NULL по ключу правой таблицы или NOT EXISTS. Оба возвращают одно и то же.
SELECT c.name
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
WHERE o.id IS NULL;
SELECT c.name
FROM customers AS c
WHERE NOT EXISTS (
SELECT 1 FROM orders AS o WHERE o.customer_id = c.id
);
name
------
Sofiia
Третий вариант — NOT IN (SELECT customer_id FROM orders) — опасен: если в подзапросе встретится хотя бы один NULL, запрос не вернёт ни одной строки. Что хотят услышать: что вы знаете об этой ловушке и поэтому выбираете NOT EXISTS.
Чем отличаются COUNT(*), COUNT(столбец) и COUNT(DISTINCT столбец)?
COUNT(*) считает строки, COUNT(столбец) — строки, где столбец не NULL, COUNT(DISTINCT столбец) — количество разных значений, тоже без NULL. Остальные агрегатные функции — SUM, AVG, MIN, MAX — пустые значения пропускают.
SELECT COUNT(*) AS all_rows,
COUNT(amount) AS with_amount,
COUNT(DISTINCT amount) AS distinct_amounts,
SUM(amount) AS total,
AVG(amount) AS avg_amount
FROM orders;
all_rows with_amount distinct_amounts total avg_amount
-------- ----------- ---------------- ----- ----------
9 8 5 7200 900.0
Среднее равно 7200 / 8, а не 7200 / 9: заказ без суммы в расчёт не попал. Если пустую сумму нужно считать нулём, пишут AVG(COALESCE(amount, 0)) — и это уже другое число, 800. Какой вариант правильный, решает смысл данных, а не SQL.
Как NULL ведёт себя в сравнениях и фильтрах?
NULL означает «значение неизвестно», поэтому любое сравнение с ним даёт не истину и не ложь, а NULL. Проверяют его только через IS NULL и IS NOT NULL, а заменяют функцией COALESCE.
SELECT NULL = NULL AS eq_null,
NULL IS NULL AS is_null,
COALESCE(NULL, 0) AS coalesced,
1 NOT IN (2, NULL) AS not_in_with_null;
eq_null is_null coalesced not_in_with_null
------- ------- --------- ----------------
1 0
Пустая ячейка в выводе — это NULL. Практическое следствие: запрос WHERE city <> 'Kyiv' на нашей таблице возвращает двух клиентов, а не трёх — Maksym с неизвестным городом не попадает ни в «Киев», ни в «не Киев». Чтобы он попал, добавляют OR city IS NULL. При сортировке по возрастанию SQLite и MySQL ставят NULL первыми, PostgreSQL — последними.
Чем подзапрос отличается от CTE?
Подзапрос — это запрос внутри другого запроса; CTE (общее табличное выражение, WITH) — тот же подзапрос, вынесенный наверх и получивший имя. Результат одинаковый, разница в читаемости: CTE можно читать сверху вниз по шагам и использовать в запросе несколько раз.
WITH customer_revenue AS (
SELECT customer_id, SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY customer_id
)
SELECT c.name, r.revenue
FROM customer_revenue AS r
JOIN customers AS c ON c.id = r.customer_id
WHERE r.revenue > (SELECT AVG(revenue) FROM customer_revenue)
ORDER BY r.revenue DESC;
name revenue
----- -------
Iryna 3500
Olena 2800
Здесь customer_revenue используется дважды: как источник строк и для расчёта средней выручки на клиента (2250). С вложенными подзапросами этот расчёт пришлось бы написать два раза. CTE поддерживают SQLite, PostgreSQL и MySQL начиная с версии 8.0.
Что такое оконная функция и чем она отличается от GROUP BY?
Оконная функция считает значение по группе строк, но не схлопывает их: в результате остаётся каждая исходная строка, и рядом с ней появляется вычисленное значение. GROUP BY оставляет одну строку на группу.
SELECT id, customer_id, amount,
SUM(amount) OVER (PARTITION BY customer_id) AS customer_total
FROM orders
WHERE status = 'paid'
ORDER BY customer_id, id;
id customer_id amount customer_total
-- ----------- ------ --------------
1 1 1200 2800
2 1 800 2800
8 1 800 2800
3 2 450 450
5 3 2000 3500
6 3 1200 3500
9 3 300 3500
Отсюда один шаг до доли заказа в выручке клиента: 100.0 * amount / SUM(amount) OVER (PARTITION BY customer_id). PARTITION BY задаёт, на какие группы делить строки, ORDER BY внутри OVER — порядок внутри группы. Подробности — в документации SQLite и PostgreSQL; в MySQL оконные функции есть с версии 8.0.
Чем отличаются ROW_NUMBER, RANK и DENSE_RANK?
Все три нумеруют строки в заданном порядке, а различаются поведением при одинаковых значениях. ROW_NUMBER всегда даёт уникальные номера, RANK ставит равным строкам одинаковый номер и затем пропускает номера, DENSE_RANK ставит одинаковый номер без пропусков.
SELECT id, amount,
ROW_NUMBER() OVER (ORDER BY amount DESC) AS row_num,
RANK() OVER (ORDER BY amount DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY amount DESC) AS dense_rnk
FROM orders
WHERE status = 'paid'
ORDER BY amount DESC, id;
id amount row_num rnk dense_rnk
-- ------ ------- --- ---------
5 2000 1 1 1
1 1200 2 2 2
6 1200 3 2 2
2 800 4 4 3
8 800 5 4 3
3 450 6 6 4
9 300 7 7 5
Что хотят услышать: когда что выбирать. «Одна строка на клиента» — ROW_NUMBER. «Три самые большие суммы, включая совпадения» — DENSE_RANK. И оговорку: при равных значениях ROW_NUMBER распределяет номера между ними произвольно, поэтому в ORDER BY окна добавляют второй столбец, например id.
Как посчитать накопительный итог?
Функцией SUM с окном, в котором задан порядок: SUM(amount) OVER (ORDER BY order_date). Важная деталь — рамка окна: по умолчанию она включает все строки с тем же значением сортировки, что и текущая.
SELECT id, order_date, amount,
SUM(amount) OVER (ORDER BY order_date) AS total_default,
SUM(amount) OVER (
ORDER BY order_date, id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS total_rows
FROM orders
WHERE amount IS NOT NULL
ORDER BY order_date, id;
id order_date amount total_default total_rows
-- ---------- ------ ------------- ----------
1 2026-01-12 1200 1200 1200
3 2026-01-28 450 1650 1650
2 2026-02-05 800 2900 2450
4 2026-02-05 450 2900 2900
5 2026-02-10 2000 4900 4900
6 2026-03-02 1200 6100 6100
8 2026-03-20 800 6900 6900
9 2026-03-28 300 7200 7200
Два заказа от 5 февраля в столбце total_default получили одинаковый итог 2900: рамка по умолчанию — RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, и «текущая строка» в ней означает все строки с той же датой. Явная рамка ROWS с однозначной сортировкой даёт построчный итог. Поведение одинаково в SQLite, PostgreSQL и MySQL.
Как сравнить значение с предыдущим периодом?
Функцией LAG: она возвращает значение из предыдущей строки окна. Сначала данные агрегируют до нужного периода, затем к каждой строке подтягивают предыдущую.
WITH monthly AS (
SELECT strftime('%Y-%m', order_date) AS month,
SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY strftime('%Y-%m', order_date)
)
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_revenue,
revenue - LAG(revenue) OVER (ORDER BY month) AS diff
FROM monthly
ORDER BY month;
month revenue prev_revenue diff
------- ------- ------------ ----
2026-01 1650
2026-02 2800 1650 1150
2026-03 2300 2800 -500
У первого месяца предыдущего значения нет, поэтому LAG вернул NULL, и разница тоже NULL. Парная функция LEAD смотрит на следующую строку. Месяц из даты в каждой СУБД получают по-своему: strftime('%Y-%m', order_date) в SQLite, to_char(order_date, 'YYYY-MM') в PostgreSQL, DATE_FORMAT(order_date, '%Y-%m') в MySQL.
Как найти и удалить дубликаты?
Найти — группировкой по столбцам, которые должны быть уникальными, с условием HAVING COUNT(*) > 1. Оставить по одной строке — через ROW_NUMBER с PARTITION BY по тем же столбцам. Пример на таблице заявок, где один адрес почты встречается несколько раз:
CREATE TABLE leads (
id INTEGER PRIMARY KEY,
email TEXT NOT NULL,
created_at TEXT NOT NULL
);
INSERT INTO leads VALUES
(1, '[email protected]', '2026-03-01'),
(2, '[email protected]', '2026-03-02'),
(3, '[email protected]', '2026-03-05'),
(4, '[email protected]', '2026-03-06'),
(5, '[email protected]', '2026-03-09'),
(6, '[email protected]', '2026-03-10');
SELECT email, COUNT(*) AS cnt
FROM leads
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY cnt DESC;
email cnt
---------------- ---
[email protected] 3
[email protected] 2
Первая заявка каждого человека:
SELECT id, email, created_at
FROM (
SELECT id, email, created_at,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at) AS rn
FROM leads
) AS t
WHERE rn = 1
ORDER BY id;
id email created_at
-- ----------------- ----------
1 [email protected] 2026-03-01
2 [email protected] 2026-03-02
4 [email protected] 2026-03-06
Физически удалить лишние строки можно запросом DELETE FROM leads WHERE id NOT IN (SELECT MIN(id) FROM leads GROUP BY email) — в SQLite он оставляет те же три строки, так же он работает в PostgreSQL. MySQL такой запрос отклонит: там нельзя в подзапросе читать таблицу, из которой удаляете, и подзапрос оборачивают в производную таблицу. Что хотят услышать: что сначала вы выясните, какая строка считается «правильной» и откуда дубликаты взялись, и только потом будете удалять.
Вопросы по статистике
По статистике у Junior проверяют не формулы, а понимание: какую меру выбрать, что означает разброс и как не сделать вывод, которого данные не поддерживают. Определения и примеры можно сверить со справочником NIST/SEMATECH e-Handbook of Statistical Methods.
Чем среднее отличается от медианы и когда что использовать?
Среднее — сумма значений, делённая на их количество; медиана — значение посередине упорядоченного ряда. Среднее чувствительно к выбросам, медиана — нет, поэтому для скошенных данных (доходы, чеки, время на сайте) честнее показывать медиану.
import statistics as st
salaries = [900, 1000, 1100, 1200, 1300, 9000]
print(st.mean(salaries))
print(st.median(salaries))
print(round(st.pstdev(salaries), 1)) # population standard deviation
print(round(st.stdev(salaries), 1)) # sample standard deviation (n - 1)
2416.6666666666665
1150.0
2947.0
3228.3
Одно значение 9000 подняло среднее до 2417, хотя пятеро из шести получают не больше 1300. Медиана 1150 описывает «типичного» человека лучше. Что хотят услышать: что вы сначала посмотрите на распределение и только потом выберете меру, а в отчёте покажете обе, если они сильно расходятся.
Что такое дисперсия и стандартное отклонение?
Дисперсия — средний квадрат отклонения значений от среднего, стандартное отклонение — корень из дисперсии. Обе показывают разброс, но стандартное отклонение выражено в тех же единицах, что и сами данные, поэтому его проще интерпретировать.
На собеседовании часто уточняют разницу между генеральной и выборочной формулой: для выборки сумму квадратов делят на n − 1, а не на n, чтобы оценка разброса не была заниженной. В примере выше это 3228,3 против 2947,0. В Excel это функции STDEV.S и STDEV.P, в pandas метод std() по умолчанию считает выборочный вариант. И ещё одно наблюдение из того же примера: выброс раздувает стандартное отклонение так же, как среднее.
Что такое нормальное распределение и какие ещё распределения вы знаете?
Нормальное распределение — симметричное, колоколообразное, полностью задаётся средним и стандартным отклонением; в пределах одного, двух и трёх стандартных отклонений от среднего лежит примерно 68, 95 и 99,7 % значений. Многие статистические методы опираются на него.
Данные аналитика часто нормальными не являются. Суммы покупок и доходы скошены вправо — длинный хвост из больших значений. Количество событий за период (заказы в час) описывает распределение Пуассона. Исход «да / нет» (купил или нет) — биномиальное. Что хотят услышать: что вы проверяете форму распределения гистограммой, прежде чем применять среднее, стандартное отклонение или тест, рассчитанный на нормальность.
Чем корреляция отличается от причинности?
Корреляция показывает, что две величины меняются согласованно; причинность — что изменение одной вызывает изменение другой. Из первого второе не следует.
Связь может объясняться третьим фактором: продажи мороженого и число обращений с солнечными ожогами растут вместе, потому что оба зависят от погоды. Причина и следствие могут быть перепутаны местами. Наконец, при большом числе метрик какие-то совпадут случайно. Коэффициент Пирсона к тому же измеряет только линейную связь и чувствителен к выбросам. Что хотят услышать: что причинность проверяют экспериментом — A/B-тестом, — а по наблюдательным данным формулируют гипотезу, а не вывод.
Что такое p-value?
P-value — это вероятность получить такой же или более сильный эффект, как в наших данных, при условии, что на самом деле различия нет (верна нулевая гипотеза). Чем оно меньше, тем хуже данные согласуются с предположением «эффекта нет».
Типичная ошибка — сказать, что p-value — это вероятность того, что нулевая гипотеза верна, или вероятность, что результат случаен. Это неверно: p-value считается в предположении, что гипотеза уже верна. Ещё два уточнения, которые ценят интервьюеры. Порог значимости (часто 0,05) выбирают до эксперимента, а не после. И статистическая значимость ничего не говорит о размере эффекта: на большой выборке значимой окажется и разница, которая бизнесу безразлична. Эти положения сформулированы в заявлении Американской статистической ассоциации о p-value.
Как устроен A/B-тест?
Пользователей случайно делят на группы, одной показывают текущий вариант, другой — изменённый, и сравнивают заранее выбранную метрику. Случайное распределение нужно, чтобы группы отличались только самим изменением.
Порядок действий, который стоит назвать:
- сформулировать гипотезу и одну главную метрику;
- до запуска определить минимальный эффект, который важен, уровень значимости и нужный размер выборки;
- запустить тест на полный цикл — обычно кратно неделям, чтобы учесть будни и выходные;
- не останавливать тест в момент, когда разница «стала значимой»: подглядывание увеличивает число ложных срабатываний;
- проверить, что группы получились ожидаемого размера, и только потом сравнивать метрику.
Что хотят услышать: что решение принимают по заранее объявленным правилам, а не подбирают метрику и сегмент под желаемый результат.
Что такое смещение выборки и как его заметить?
Смещение выборки возникает, когда данные, по которым мы делаем вывод, систематически отличаются от совокупности, о которой хотим его сделать. Тогда даже аккуратный расчёт даёт неверный ответ.
Примеры из практики аналитика: опрос об удовлетворённости, на который отвечают только самые довольные и самые недовольные; анализ «успешных клиентов» без тех, кто ушёл (ошибка выжившего); вывод о всех пользователях по данным одного канала привлечения. Чтобы заметить смещение, спрашивают: как эти строки попали в таблицу и кого в ней нет? Затем сравнивают состав выборки с известным составом всей базы — по каналам, регионам, давности регистрации.
Вопросы по Excel и таблицам
По таблицам спрашивают три вещи: функции поиска, сводные таблицы и очистку данных. Ответы одинаково применимы к Excel и Google Sheets; названия функций приведены английские. О том, где заканчиваются возможности таблиц и начинается BI, есть отдельный разбор — Power BI или Excel.
Чем VLOOKUP отличается от XLOOKUP и INDEX + MATCH?
VLOOKUP ищет значение в первом столбце диапазона и возвращает значение из столбца правее по его номеру. XLOOKUP принимает столбец поиска и столбец результата отдельно, поэтому умеет искать влево и не ломается при вставке столбцов. Связка INDEX + MATCH делает то же в версиях, где XLOOKUP нет.
Детали, которые спрашивают:
- у
VLOOKUPпоследний аргумент по умолчанию означает приблизительное совпадение, поэтому для точного поиска пишутFALSE; уXLOOKUPточное совпадение — по умолчанию; - если значение не найдено,
VLOOKUPвернёт#N/A, а вXLOOKUPесть аргумент для значения «если не найдено»; - при нескольких совпадениях обе функции возвращают первое — дубликаты в справочнике дают тихую ошибку.
Описания аргументов — в справке Microsoft по VLOOKUP и XLOOKUP.
Что такое сводная таблица и когда она нужна?
Сводная таблица — инструмент, который группирует строки исходной таблицы по выбранным полям и считает по группам итоги: сумму, количество, среднее. По смыслу это GROUP BY без написания запроса.
Поля раскладывают по четырём областям: строки, столбцы, значения и фильтры. Сводная нужна, когда надо быстро посмотреть на данные в разных разрезах — выручку по месяцам и городам, количество заказов по статусам. Что хотят услышать: требования к исходным данным. Одна строка — одна запись, одна строка заголовков, без объединённых ячеек и промежуточных итогов внутри диапазона, числа и даты хранятся как числа и даты, а не как текст. Пошаговое описание — в справке Microsoft по сводным таблицам.
Как вы очищаете данные в таблице перед анализом?
Сначала смотрю, что именно не так, и только потом исправляю — на копии, не трогая исходный лист. Порядок проверки обычно такой:
- Структура: одна строка заголовков, нет объединённых ячеек и пустых строк внутри данных.
- Типы: числа и даты, сохранённые как текст, — их выдают выравнивание по левому краю и сумма, равная нулю.
- Текст: лишние пробелы (
TRIM), разный регистр, варианты написания одного значения — «Киев», «киев», «Kyiv». - Дубликаты: сначала подсчитать, потом решить, какие строки лишние, и только затем удалять.
- Пропуски и выбросы: понять их причину, прежде чем заполнять или отбрасывать.
Что хотят услышать: что каждое изменение вы можете воспроизвести и объяснить. Поэтому повторяемую очистку переносят из ручных правок в Power Query, SQL или pandas.
Вопросы по Power BI и визуализации
В блоке BI проверяют, понимаете ли вы модель данных: откуда отчёт берёт цифру и почему она меняется при выборе фильтра. Формулы ниже — стандартные меры; запустить их вне Power BI нельзя, поэтому они приведены без вывода и сверены с справочником функций DAX на Microsoft Learn. Пошаговое введение в язык — в статье DAX для начинающих.
Что такое схема «звезда» и зачем она нужна?
«Звезда» — это модель, в которой в центре стоит таблица фактов с событиями и числами (продажи, заказы), а вокруг неё — таблицы измерений с описаниями (клиенты, товары, календарь). Факты связаны с измерениями по ключам.
Такая модель даёт три преимущества: фильтры из измерений предсказуемо распространяются на факты, меры пишутся проще, а модель занимает меньше памяти, потому что текстовые описания не повторяются в каждой строке фактов. Противоположность — одна широкая таблица, где всё смешано: на ней формулы усложняются, а итоги начинают двоиться. Microsoft прямо рекомендует «звезду» для моделей Power BI в руководстве по схеме «звезда».
Какие бывают связи между таблицами в Power BI?
Связь описывают две характеристики: кардинальность и направление фильтрации. Кардинальность бывает «один ко многим», «один к одному» и «многие ко многим»; направление — одностороннее или двустороннее.
Рабочий стандарт — «один ко многим» с односторонним фильтром: измерение (сторона «один») фильтрует таблицу фактов (сторона «многие»). Выбрали город в таблице клиентов — отфильтровались продажи. Двустороннюю фильтрацию и связи «многие ко многим» включают только осознанно: они могут давать неоднозначные пути фильтра и неожиданные итоги. Между двумя таблицами активной может быть только одна связь; остальные неактивны и включаются в мере функцией USERELATIONSHIP. Подробнее — в документации о связях в моделях.
Чем мера отличается от вычисляемого столбца?
Вычисляемый столбец считается для каждой строки таблицы при обновлении данных и хранится в модели. Мера не хранится: она вычисляется в момент запроса для того набора фильтров, который действует в конкретной ячейке отчёта.
Amount = Sales[Quantity] * Sales[Price]
Total Sales = SUM(Sales[Amount])
Первая формула — вычисляемый столбец в таблице Sales: она видит текущую строку. Вторая — мера: одно и то же определение возвращает общую сумму в карточке, сумму по городу в строке таблицы и сумму за месяц на графике. Практическое правило: столбец нужен, когда значение используется в срезе, оси или связи; всё, что является итогом, средним или долей, — мера. Типичная ошибка: посчитать долю или среднее в столбце и затем суммировать её в визуале. Официальные описания: меры и вычисляемые столбцы.
Что делает CALCULATE и что такое контекст фильтра?
Контекст фильтра — это набор фильтров, действующих на ячейку отчёта: срезы, строки и столбцы визуала, фильтры страницы. CALCULATE вычисляет выражение в изменённом контексте фильтра: добавляет новые фильтры, заменяет существующие или снимает их.
Kyiv Sales =
CALCULATE([Total Sales], Customers[City] = "Kyiv")
Sales Share =
DIVIDE(
[Total Sales],
CALCULATE([Total Sales], ALL(Customers[City]))
)
Первая мера всегда показывает продажи Киева: фильтр по городу в CALCULATE заменяет тот, что пришёл из визуала. Вторая считает долю города: в знаменателе ALL снимает фильтр по городу, поэтому там общий итог. DIVIDE используют вместо оператора деления, чтобы деление на ноль возвращало пустое значение, а не ошибку.
Что хотят услышать: разницу между контекстом фильтра и контекстом строки. Контекст строки есть в вычисляемых столбцах и функциях-итераторах вроде SUMX; CALCULATE превращает его в контекст фильтра — это называют переходом контекста. Синтаксис и примеры — в описании CALCULATE.
Как вы выбираете тип диаграммы?
От вопроса, на который должен ответить график, а не от того, что красивее. Сначала формулирую вопрос одной фразой, затем подбираю форму.
| Вопрос | Диаграмма |
|---|---|
| Как показатель менялся во времени? | Линейный график |
| Какая категория больше? | Столбчатая или линейчатая диаграмма, отсортированная по значению |
| Из чего состоит целое? | Столбчатая с накоплением; круговая — только для двух-трёх долей |
| Как распределены значения? | Гистограмма |
| Связаны ли две величины? | Точечная диаграмма |
| Одно число и его сравнение с целью | Карточка с показателем |
К этому стоит добавить: ось столбчатой диаграммы начинается с нуля, цвет несёт смысл, а не украшает, и на одном экране дашборда остаётся только то, что помогает принять решение. Список визуалов Power BI — в документации Microsoft.
Те же темы — с преподавателем и домашними заданиями
Программа курса Data Analytics в Prog Academy состоит из четырёх модулей: Power BI, Python для дата аналитики, AI Start и SQL. Полная программа рассчитана на 5 месяцев; в ней есть модель данных и функции DAX, SQL от SELECT до подзапросов, NumPy и Pandas, очистка данных и основы статистики.
Программа курса Data Analytics →Вопросы по Python и pandas
Если Python указан в вакансии, спрашивают пять операций pandas: прочитать файл, отфильтровать, сгруппировать, объединить таблицы и обработать пропуски. Примеры работают с файлом orders.csv — теми же заказами, что и в блоке SQL, но в «грязном» виде: одна строка продублирована, у одной нет города и суммы. Более широкий обзор — в статье Python для анализа данных.
order_id,customer,city,order_date,amount,status
1,Olena,Kyiv,2026-01-12,1200,paid
2,Olena,Kyiv,2026-02-05,800,paid
3,Taras,Lviv,2026-01-28,450,paid
4,Taras,Lviv,2026-02-05,450,refunded
5,Iryna,Kyiv,2026-02-10,2000,paid
6,Iryna,Kyiv,2026-03-02,1200,paid
7,Maksym,,2026-03-15,,pending
8,Olena,Kyiv,2026-03-20,800,paid
8,Olena,Kyiv,2026-03-20,800,paid
9,Iryna,Kyiv,2026-03-28,300,paid
С чего вы начинаете работу с новым набором данных в pandas?
С трёх проверок: размер таблицы, типы столбцов и количество пропусков. Они занимают три строки и сразу показывают, чему в данных нельзя доверять.
import pandas as pd
df = pd.read_csv("orders.csv", parse_dates=["order_date"])
print(df.shape)
print(df.dtypes)
print(df.isna().sum())
(10, 6)
order_id int64
customer object
city object
order_date datetime64[ns]
amount float64
status object
dtype: object
order_id 0
customer 0
city 1
order_date 0
amount 1
status 0
dtype: int64
Уже видно два факта. Столбец amount стал дробным, хотя в файле целые числа: в нём есть пропуск, а обычный целочисленный тип NaN хранить не умеет. И дата прочиталась как дата только потому, что указан parse_dates, — без него это была бы строка.
Как отфильтровать строки по нескольким условиям?
Логической маской в квадратных скобках: каждое условие берут в круглые скобки и соединяют операторами & (и), | (или), ~ (не).
big_kyiv = df[(df["city"] == "Kyiv") & (df["amount"] >= 1000)]
print(big_kyiv[["order_id", "customer", "amount"]])
order_id customer amount
0 1 Olena 1200.0
4 5 Iryna 2000.0
5 6 Iryna 1200.0
Типичная ошибка: написать and вместо & или забыть скобки. Слова and и or работают с одним логическим значением, а не со столбцом, и pandas выдаст ошибку о неоднозначности. Скобки нужны, потому что у & приоритет выше, чем у сравнения. Для выбора строк и столбцов одновременно используют df.loc[маска, столбцы]; правила индексации описаны в документации pandas.
Как сгруппировать данные и посчитать несколько показателей?
Методом groupby с agg: в agg для каждого нового столбца указывают исходный столбец и функцию. Это прямой аналог GROUP BY в SQL.
df = df.drop_duplicates()
report = (
df[df["status"] == "paid"]
.groupby("customer", as_index=False)
.agg(orders=("order_id", "count"), revenue=("amount", "sum"))
.sort_values("revenue", ascending=False)
)
print(report)
customer orders revenue
0 Iryna 3 3500.0
1 Olena 3 2800.0
2 Taras 1 450.0
Цифры совпадают с SQL-запросом из блока выше — так и должно быть, если данные очищены одинаково. Без drop_duplicates() у Olena получилось бы четыре заказа и 3600. Одно отличие от SQL стоит назвать: по умолчанию groupby отбрасывает строки, где ключ группировки пуст, а GROUP BY собирает NULL в отдельную группу. В pandas это поведение меняет параметр dropna=False (руководство по groupby).
Как объединить две таблицы и чем merge похож на JOIN?
Методом merge: параметр on задаёт ключ, а how — тип объединения: inner, left, right, outer. Это те же JOIN, только по умолчанию merge делает inner.
customers = pd.DataFrame({
"customer": ["Olena", "Taras", "Iryna", "Maksym", "Sofiia"],
"segment": ["B2C", "B2C", "B2B", "B2C", "B2B"],
})
orders = pd.read_csv("orders.csv").drop_duplicates()
merged = customers.merge(orders, on="customer", how="left", indicator=True)
print(merged["_merge"].value_counts())
print(merged.loc[merged["_merge"] == "left_only", "customer"].tolist())
_merge
both 9
left_only 1
right_only 0
Name: count, dtype: int64
['Sofiia']
Параметр indicator=True добавляет столбец, который показывает, нашлась ли пара для строки, — так находят клиентов без заказов. Что хотят услышать: что после объединения вы проверяете количество строк. Если ключ в правой таблице не уникален, строки размножаются и суммы завышаются; защититься помогает параметр validate, например validate="one_to_many" (руководство по merge).
Как вы работаете с пропущенными значениями?
Сначала считаю их и выясняю причину, затем выбираю одно из трёх: оставить, удалить строки или заполнить. Универсального правильного варианта нет — он зависит от того, что означает пропуск.
df = pd.read_csv("orders.csv").drop_duplicates()
print(df["amount"].mean()) # NaN is skipped
print(df["amount"].fillna(0).mean()) # NaN counted as 0
print(len(df.dropna(subset=["amount"])))
df["city"] = df["city"].fillna("Unknown")
print(df["city"].value_counts())
900.0
800.0
8
city
Kyiv 6
Lviv 2
Unknown 1
Name: count, dtype: int64
Средний чек 900 или 800 — зависит от того, считать ли заказ без суммы нулевым. Агрегатные методы pandas пропуски по умолчанию пропускают, как и SQL. Заполнять числовой столбец нулём, средним или медианой можно только с пониманием последствий: заполнение средним, например, искусственно уменьшает разброс. Для категорий честнее отдельное значение «Unknown», как в примере. Обзор инструментов — в руководстве по пропущенным данным.
Вопросы по продуктовым и бизнес-метрикам
В блоке метрик проверяют, понимаете ли вы, что стоит за числом: как оно считается, от чего зависит и какое решение по нему принимают. Формулы у компаний различаются, поэтому в ответе всегда уточняйте определение: что в числителе, что в знаменателе и за какой период. Сам термин разобран в глоссарии — что такое KPI.
Что такое конверсия и воронка?
Конверсия — доля пользователей, совершивших целевое действие, от тех, кто мог его совершить. Воронка — последовательность шагов к этому действию с конверсией между соседними шагами: просмотр товара, корзина, оплата.
Вопросы, которые нужно задать, прежде чем считать: что в знаменателе — пользователи, сессии или визиты; за какой срок действие засчитывается; учитываются ли пользователи, попавшие на шаг в обход предыдущего. От ответов число меняется в разы. Воронка полезна тем, что показывает, на каком шаге теряется больше всего людей, — туда и направляют усилия. Запрос для расчёта воронки есть в разделе практических задач.
Что такое удержание и когортный анализ?
Удержание (retention) — доля пользователей, которые вернулись в продукт через заданное время после первого визита или покупки. Когорта — группа пользователей с общим стартовым событием в один период, например все, кто зарегистрировался в марте.
Когортный анализ сравнивает удержание разных когорт: строки таблицы — месяц регистрации, столбцы — номер месяца жизни, в ячейках — доля активных. Он нужен, потому что общее среднее по базе скрывает изменения: приток новых пользователей маскирует то, что старые уходят быстрее. По когортам видно, улучшилось ли удержание после изменения в продукте. Что хотят услышать: уточнение, что считается возвращением — любой визит, целевое действие или покупка.
Что такое LTV и как его посчитать?
LTV (lifetime value) — доход или прибыль, которую один клиент приносит компании за всё время отношений с ней. Простейшая оценка — средний доход с клиента за период, умноженный на среднее число периодов, которые клиент остаётся активным.
На практике уточняют три вещи. Считают ли по выручке или по марже — для решений о рекламе нужна маржа. За какой горизонт — «за всё время» часто заменяют на 6 или 12 месяцев, потому что дальше данных нет. И по каким когортам — LTV клиентов из разных каналов может различаться в разы. Используют метрику в паре со стоимостью привлечения клиента: если привлечение стоит дороже, чем клиент приносит, рост убыточен.
Метрика упала на 20 % — как вы будете разбираться?
Сначала проверю, что падение настоящее, затем локализую его по сегментам и шагам воронки и только потом буду искать причину. Это вопрос на структуру мышления, поэтому отвечать стоит по шагам.
- Данные. Не сломался ли сбор событий, загрузка или расчёт; не менялось ли определение метрики; полный ли последний день.
- Масштаб. Резкое падение или постепенное, с какой даты, бывало ли такое раньше — сезонность, праздники, день недели.
- Числитель и знаменатель. Что именно изменилось: стало меньше покупок или больше посетителей при тех же покупках.
- Сегменты. Платформа, канал привлечения, страна, новые и вернувшиеся пользователи, версия приложения. Падение во всех сегментах и в одном — разные истории.
- Воронка. На каком шаге конверсия просела.
- События. Что произошло в эту дату: релиз, изменение цены, запуск или остановка рекламы, сбой у платёжного партнёра.
- Вывод. Гипотеза, чем её подтвердить и что предложить.
Типичная ошибка: сразу называть причину — «наверное, сезонность» — не проверив данные и не сузив область поиска.
Вопросы о коммуникации
Аналитика оценивают по тому, приняли ли по его выводу решение, поэтому умение объяснить результат проверяют наравне с техникой. На эти вопросы отвечают примером из своего проекта — учебного в том числе.
Как вы презентуете результаты анализа людям без технической подготовки?
Начинаю с вывода и рекомендации, а не с методики расчёта. Структура короткая: что мы хотели узнать, что обнаружили, что это означает для бизнеса и что я предлагаю сделать. Методика и оговорки идут после — для тех, кто захочет проверить.
Несколько правил, которые стоит назвать. Один слайд или один график — одна мысль, вынесенная в заголовок целым предложением. Термины заменяю на язык слушателя: не «p-value меньше 0,05», а «разница слишком велика, чтобы списать её на случайность». Называю ограничения: за какой период данные, чего в них нет, насколько надёжен вывод. И заранее готовлю ответ на вопрос «и что нам с этим делать?» — без него анализ остаётся справкой.
Что вы делаете, если задача от заказчика сформулирована нечётко?
Уточняю, какое решение человек собирается принять по результату, и уже от него определяю, что считать. Просьба «выгрузи продажи за квартал» может означать десять разных таблиц.
Вопросы, которые я задаю: для чего это нужно и что изменится в зависимости от ответа; как определяется метрика — например, считать ли возвраты; за какой период и в каких разрезах; в каком виде нужен результат и к какому сроку. Затем коротко письменно фиксирую договорённость и, если задача большая, показываю промежуточный результат, чтобы не уйти в сторону. Что хотят услышать: что вы не начинаете считать, пока не понимаете вопрос, и не исчезаете на неделю, чтобы принести не то.
Практические задачи с решениями
Практическая часть — это обычно одна-три задачи на SQL и иногда одна на pandas или таблицы. Ниже четыре типовые задачи на тех же данных. Прежде чем смотреть решение, попробуйте написать своё. Потренировать основы — SELECT, WHERE, агрегатные функции, GROUP BY и первые JOIN — можно в бесплатном курсе по SQL; полная программа от SELECT до оконных функций — на курсе SQL.
Задача 1. Последний оплаченный заказ каждого клиента
Вывести для каждого клиента его последний оплаченный заказ: имя, номер, дату и сумму. Классическая задача «одна строка на группу» — нумеруем заказы клиента от нового к старому и берём первый.
WITH ranked AS (
SELECT o.customer_id, o.id AS order_id, o.order_date, o.amount,
ROW_NUMBER() OVER (
PARTITION BY o.customer_id
ORDER BY o.order_date DESC, o.id DESC
) AS rn
FROM orders AS o
WHERE o.status = 'paid'
)
SELECT c.name, r.order_id, r.order_date, r.amount
FROM ranked AS r
JOIN customers AS c ON c.id = r.customer_id
WHERE r.rn = 1
ORDER BY c.name;
name order_id order_date amount
----- -------- ---------- ------
Iryna 9 2026-03-28 300
Olena 8 2026-03-20 800
Taras 3 2026-01-28 450
Вторая колонка сортировки o.id DESC делает результат однозначным, если у клиента два заказа в один день. Решение через MAX(order_date) и GROUP BY вернуло бы дату, но не остальные поля заказа.
Задача 2. Выручка по месяцам и рост к предыдущему месяцу
Посчитать выручку по оплаченным заказам за каждый месяц и процент изменения к предыдущему.
WITH monthly AS (
SELECT strftime('%Y-%m', order_date) AS month,
SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY strftime('%Y-%m', order_date)
)
SELECT month, revenue,
ROUND(
100.0 * (revenue - LAG(revenue) OVER (ORDER BY month))
/ LAG(revenue) OVER (ORDER BY month),
1
) AS growth_pct
FROM monthly
ORDER BY month;
month revenue growth_pct
------- ------- ----------
2026-01 1650
2026-02 2800 69.7
2026-03 2300 -17.9
Множитель 100.0, а не 100, стоит не случайно: в SQLite и PostgreSQL деление целого на целое отбрасывает дробную часть, и 2 / 8 даёт 0. В MySQL оператор / возвращает дробное число, но писать 100.0 — привычка, которая работает везде.
Задача 3. Конверсия по шагам воронки
Есть таблица событий: просмотр, добавление в корзину, покупка. Посчитать, сколько пользователей дошло до каждого шага, и конверсию между шагами.
CREATE TABLE events (
user_id INTEGER NOT NULL,
event TEXT NOT NULL,
event_date TEXT NOT NULL
);
INSERT INTO events VALUES
(1, 'view', '2026-03-01'), (1, 'cart', '2026-03-01'), (1, 'purchase', '2026-03-02'),
(2, 'view', '2026-03-01'), (2, 'cart', '2026-03-03'),
(3, 'view', '2026-03-02'),
(4, 'view', '2026-03-02'), (4, 'view', '2026-03-04'), (4, 'cart', '2026-03-04'), (4, 'purchase', '2026-03-04'),
(5, 'view', '2026-03-05'),
(6, 'view', '2026-03-05'), (6, 'cart', '2026-03-06'),
(7, 'view', '2026-03-06'),
(8, 'view', '2026-03-07');
WITH funnel AS (
SELECT COUNT(DISTINCT CASE WHEN event = 'view' THEN user_id END) AS viewed,
COUNT(DISTINCT CASE WHEN event = 'cart' THEN user_id END) AS added_to_cart,
COUNT(DISTINCT CASE WHEN event = 'purchase' THEN user_id END) AS purchased
FROM events
)
SELECT viewed, added_to_cart, purchased,
ROUND(100.0 * added_to_cart / viewed, 1) AS view_to_cart_pct,
ROUND(100.0 * purchased / added_to_cart, 1) AS cart_to_purchase_pct,
ROUND(100.0 * purchased / viewed, 1) AS view_to_purchase_pct
FROM funnel;
viewed added_to_cart purchased view_to_cart_pct cart_to_purchase_pct view_to_purchase_pct
------ ------------- --------- ---------------- -------------------- --------------------
8 4 2 50.0 50.0 25.0
Приём — условная агрегация: CASE без ветки ELSE возвращает NULL для «чужих» событий, а COUNT(DISTINCT ...) пустые значения не считает. DISTINCT обязателен: пользователь 4 смотрел товар дважды, но в воронке это один человек. На интервью стоит оговорить допущение: запрос считает тех, у кого событие было, и не проверяет порядок шагов.
Задача 4. Очистить файл и посчитать показатели по месяцам в pandas
Из файла orders.csv получить по месяцам количество оплаченных заказов, выручку и средний чек.
import pandas as pd
df = pd.read_csv("orders.csv", parse_dates=["order_date"])
df = df.drop_duplicates(subset="order_id") # 1. remove duplicates
df = df.dropna(subset=["amount"]) # 2. no amount - no revenue
df = df[df["status"] == "paid"] # 3. only paid orders
df["month"] = df["order_date"].dt.to_period("M") # 4. month of the order
monthly = (
df.groupby("month")
.agg(orders=("order_id", "count"),
revenue=("amount", "sum"),
avg_check=("amount", "mean"))
.round(1)
)
print(monthly)
orders revenue avg_check
month
2026-01 2 1650.0 825.0
2026-02 2 2800.0 1400.0
2026-03 3 2300.0 766.7
Выручка по месяцам совпала с результатом задачи 2 — это и есть проверка: один и тот же показатель, посчитанный двумя инструментами, должен сойтись. Проговаривайте каждый шаг очистки и причину: интервьюеру важно, что вы не считаете по сырым данным.
Типичные ошибки кандидатов
Большинство ошибок на собеседовании аналитика — не пробелы в знаниях, а привычка считать, не проверив данные и не уточнив вопрос. Список составлен по преподавательскому опыту автора.
- Писать запрос молча. Интервьюер оценивает ход мысли. Проговаривайте: какие таблицы, какой ключ, сколько строк ожидаете.
- Не уточнять условие. «Выручка» — с возвратами или без? «Активный клиент» — за какой срок? Вопросы к условию — плюс, а не слабость.
- Не проверять количество строк после JOIN. Размноженные строки завышают суммы, и результат выглядит правдоподобно.
- Забывать про NULL. Пустые значения в фильтрах,
NOT INи средних — источник большинства «почему не сходится». - Заучивать определения без примера. Определение p-value или контекста фильтра без примера звучит как выученный текст.
- Называть инструменты вместо результата. «Сделал дашборд в Power BI» ничего не говорит; «дашборд показал, на каком шаге теряются заявки» — говорит.
- Не знать собственный проект. Если в портфолио есть запрос или мера, которые вы не можете объяснить, их лучше убрать.
- Придумывать ответ. Честное «не знаю, но рассуждал бы так» воспринимается лучше уверенной ошибки.
- Не задавать вопросов в конце. Это читается как отсутствие интереса к работе.
Что спросить у интервьюера?
Вопросы кандидата показывают, что вы выбираете работу, а не просто ищете любую, и заодно дают понять, чем вы будете заниматься на самом деле.
- Какие задачи аналитик решает в первые три месяца? Можно пример недавней задачи?
- Где хранятся данные и кто отвечает за их качество — есть ли инженеры данных и ETL-процессы или аналитик собирает всё сам?
- Какой стек используется каждый день: СУБД, BI-инструмент, Python?
- Кто ставит задачи аналитику и как выглядит типичный запрос от бизнеса?
- Как проверяется работа: есть ли ревью запросов и отчётов?
- Сколько в работе разовых выгрузок, а сколько — исследований и регулярной отчётности?
- Кто будет моим наставником в первые месяцы и как устроен ввод в работу?
- По каким признакам через полгода вы поймёте, что я справляюсь?
- Какие следующие этапы отбора и когда ждать ответа?
План подготовки на две недели
Две недели по полтора-два часа в день хватает, чтобы повторить базу и натренировать ответы вслух, — при условии, что темы вы уже изучали. Это авторский ориентир, а не норма: если SQL или статистика для вас новые, заложите на них больше времени. О том, как профессия сочетается с AI-инструментами, — в статье AI + Data Analytics.
| Дни | Тема | Что сделать |
|---|---|---|
| 1–2 | SQL: SELECT, WHERE, GROUP BY, HAVING | Создать таблицы из статьи, написать по памяти запросы с агрегацией, объяснить вслух порядок выполнения |
| 3–4 | SQL: JOIN, NULL, подзапросы и CTE | Для каждого JOIN заранее предсказать число строк; найти клиентов без заказов тремя способами |
| 5–6 | SQL: оконные функции | Ранжирование, накопительный итог, LAG; решить задачи 1–3 без подсказок |
| 7 | Повторение SQL | Решить три задачи на время, проговаривая решение вслух |
| 8 | Статистика | Своими словами, с примером: среднее и медиана, разброс, корреляция, p-value, A/B-тест |
| 9 | Excel или Google Sheets | Функции поиска, сводная таблица, очистка «грязного» файла |
| 10 | Power BI и DAX | Собрать модель «звезда» из двух-трёх таблиц, написать меры с CALCULATE, объяснить результат |
| 11 | pandas (если есть в вакансии) | Прочитать файл, очистить, сгруппировать, объединить — задача 4 |
| 12 | Метрики | Определения конверсии, удержания, LTV; проговорить расследование падения метрики |
| 13 | Проекты и рассказ о себе | По каждому проекту: задача, данные, что сделали, результат, что улучшили бы |
| 14 | Пробное интервью | Попросить знакомого задать вопросы из статьи; записать ответы и переслушать |
Блок Power BI и DAX удобнее повторять на собственной модели, а не по конспекту. Модели данных, связи, DAX и Power Query с нуля входят в программу курса Power BI. Кто такой аналитик данных и чем его роль отличается от соседних, коротко описано в глоссарии — Data Analyst.
Частые вопросы
Сколько времени нужно на подготовку к собеседованию на Data Analyst?
Если базу вы уже учили, на повторение и тренировку обычно хватает двух недель по полтора-два часа в день: неделя на SQL, неделя на статистику, BI, метрики и рассказ о проектах. Это ориентир автора как преподавателя, а не статистика. Если SQL и статистику вы ещё не изучали, двух недель не хватит — сначала нужна сама база.
Будет ли на собеседовании live-coding по SQL?
Скорее всего, да: написать запрос при интервьюере или в общем редакторе — самый распространённый практический формат для аналитика. Обычно это одна-три задачи на JOIN, GROUP BY и оконные функции. Проговаривайте ход мысли вслух и сначала уточняйте, что считается одной строкой в таблице.
Нужен ли английский на собеседовании аналитика данных?
Английский для чтения нужен в любом случае: документация SQL, pandas и Power BI написана на английском. Разговорный уровень проверяют там, где команда или заказчик работают на английском, — обычно короткой частью интервью. Требование к уровню указывают в вакансии, поэтому его стоит проверить заранее.
Можно ли пользоваться AI-инструментами на собеседовании и в тестовом задании?
На живом интервью — только если интервьюер прямо разрешил; спросите об этом в начале. В домашнем тестовом задании правила задаёт компания: если запрета нет, пользоваться можно, но каждое решение придётся объяснить на разборе. Запрос, который вы не можете объяснить, вредит больше, чем нерешённая задача.
Что делать, если не знаешь ответа на вопрос?
Сказать об этом прямо и показать, как вы рассуждаете: что знаете о смежной теме, как проверили бы гипотезу, где посмотрели бы в документации. Интервьюер оценивает ход мысли, а не только готовый ответ. Хуже всего — уверенно придумывать: неверный ответ с уверенным тоном запоминается сильнее, чем честное «не знаю».
Дают ли тестовое задание и сколько оно занимает?
Часто дают: набор данных и несколько вопросов бизнеса, на которые нужно ответить запросами, расчётами и коротким выводом или дашбордом. Объём у компаний разный, срок и ожидаемое время обычно указаны в самом задании — если нет, уточните. Оценивают не только цифры, но и то, как вы проверили данные и сформулировали выводы.
Что важнее для Junior Data Analyst: SQL, Excel или Power BI?
SQL — его проверяют практически на каждом техническом интервью аналитика, потому что данные лежат в базах. Excel или Google Sheets и один BI-инструмент нужны как рабочие инструменты для расчётов и отчётов. Точный набор зависит от вакансии, поэтому перечитайте требования и повторите именно те инструменты, которые в них названы.
Нужен ли Python начинающему аналитику данных?
Зависит от вакансии. Во многих позициях Junior хватает SQL, таблиц и BI-инструмента, а Python идёт в разделе «будет плюсом». Если Python указан в требованиях, ждите вопросов по pandas: чтение файла, фильтрация, groupby, merge, пропуски. Уверенный SQL при этом важнее поверхностного знания pandas.
Нужно ли портфолио для собеседования на Junior Data Analyst?
Формально его требуют не всегда, но без коммерческого опыта это главный способ показать, что вы умеете работать с данными. Достаточно двух-трёх проектов: SQL-запросы к открытому набору данных, дашборд в Power BI и небольшой анализ в pandas. Будьте готовы объяснить каждое решение и каждый вывод.
Источники
- SQLite documentation: SELECT
- SQLite documentation: Window Functions
- SQLite documentation: The WITH Clause
- SQLite documentation: NULL Handling in SQLite Versus Other Database Engines
- PostgreSQL documentation: Window Functions
- PostgreSQL documentation: Table Expressions (JOIN, GROUP BY, HAVING)
- MySQL 8.4 Reference Manual: Window Functions
- pandas documentation: Indexing and selecting data
- pandas documentation: Group by — split-apply-combine
- pandas documentation: Merge, join, concatenate and compare
- pandas documentation: Working with missing data
- Python documentation: statistics — Mathematical statistics functions
- Microsoft Learn: DAX function reference
- Microsoft Learn: CALCULATE function (DAX)
- Microsoft Learn: Understand star schema and the importance for Power BI
- Microsoft Learn: Model relationships in Power BI Desktop
- Microsoft Learn: Create measures for data analysis in Power BI Desktop
- Microsoft Learn: Create calculated columns in Power BI Desktop
- Microsoft Learn: Visualization types in Power BI
- Microsoft Support: VLOOKUP function
- Microsoft Support: XLOOKUP function
- Microsoft Support: Create a PivotTable to analyze worksheet data
- NIST/SEMATECH e-Handbook of Statistical Methods
- Wasserstein R. L., Lazar N. A.: The ASA Statement on p-Values (The American Statistician, 2016)
