Prog Academy
RU UA
Вопросы на собеседовании Data Analyst: 39 вопросов с ответами и задачи по SQL
Карьера в IT

Вопросы на собеседовании Data Analyst: 39 вопросов с ответами и задачи по SQL

На собеседовании Junior Data Analyst проверяют четыре вещи: умеете ли вы достать данные запросом SQL, понимаете ли базовую статистику, можете ли собрать отчёт в таблицах или BI-инструменте и способны ли объяснить цифру человеку из бизнеса. В статье — 39 вопросов с короткими ответами, сгруппированных по семи темам: SQL, статистика, Excel, Power BI, pandas, продуктовые метрики и коммуникация. Самый большой блок — SQL, с запросами и их реальным результатом. После вопросов — четыре практические задачи с решениями, типичные ошибки и план подготовки на две недели.

Я тренер Prog Academy по Power BI и преподаватель высшей школы, поэтому вижу подготовку к собеседованиям со стороны студентов. Чаще всего подводит не забытая функция, а неумение объяснить, почему цифра получилась именно такой: откуда взялись строки, что стало с пустыми значениями, почему итог не сходится с соседним отчётом. Ответы ниже построены так, чтобы вы могли произнести их вслух, а затем показать на примере.

Актуально на октябрь 2026 года

Все 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-valueJunior
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-тест?

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

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

  1. сформулировать гипотезу и одну главную метрику;
  2. до запуска определить минимальный эффект, который важен, уровень значимости и нужный размер выборки;
  3. запустить тест на полный цикл — обычно кратно неделям, чтобы учесть будни и выходные;
  4. не останавливать тест в момент, когда разница «стала значимой»: подглядывание увеличивает число ложных срабатываний;
  5. проверить, что группы получились ожидаемого размера, и только потом сравнивать метрику.

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

Что такое смещение выборки и как его заметить?

Смещение выборки возникает, когда данные, по которым мы делаем вывод, систематически отличаются от совокупности, о которой хотим его сделать. Тогда даже аккуратный расчёт даёт неверный ответ.

Примеры из практики аналитика: опрос об удовлетворённости, на который отвечают только самые довольные и самые недовольные; анализ «успешных клиентов» без тех, кто ушёл (ошибка выжившего); вывод о всех пользователях по данным одного канала привлечения. Чтобы заметить смещение, спрашивают: как эти строки попали в таблицу и кого в ней нет? Затем сравнивают состав выборки с известным составом всей базы — по каналам, регионам, давности регистрации.

Вопросы по 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 по сводным таблицам.

Как вы очищаете данные в таблице перед анализом?

Сначала смотрю, что именно не так, и только потом исправляю — на копии, не трогая исходный лист. Порядок проверки обычно такой:

  1. Структура: одна строка заголовков, нет объединённых ячеек и пустых строк внутри данных.
  2. Типы: числа и даты, сохранённые как текст, — их выдают выравнивание по левому краю и сумма, равная нулю.
  3. Текст: лишние пробелы (TRIM), разный регистр, варианты написания одного значения — «Киев», «киев», «Kyiv».
  4. Дубликаты: сначала подсчитать, потом решить, какие строки лишние, и только затем удалять.
  5. Пропуски и выбросы: понять их причину, прежде чем заполнять или отбрасывать.

Что хотят услышать: что каждое изменение вы можете воспроизвести и объяснить. Поэтому повторяемую очистку переносят из ручных правок в 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.

DA

Те же темы — с преподавателем и домашними заданиями

Программа курса 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 % — как вы будете разбираться?

Сначала проверю, что падение настоящее, затем локализую его по сегментам и шагам воронки и только потом буду искать причину. Это вопрос на структуру мышления, поэтому отвечать стоит по шагам.

  1. Данные. Не сломался ли сбор событий, загрузка или расчёт; не менялось ли определение метрики; полный ли последний день.
  2. Масштаб. Резкое падение или постепенное, с какой даты, бывало ли такое раньше — сезонность, праздники, день недели.
  3. Числитель и знаменатель. Что именно изменилось: стало меньше покупок или больше посетителей при тех же покупках.
  4. Сегменты. Платформа, канал привлечения, страна, новые и вернувшиеся пользователи, версия приложения. Падение во всех сегментах и в одном — разные истории.
  5. Воронка. На каком шаге конверсия просела.
  6. События. Что произошло в эту дату: релиз, изменение цены, запуск или остановка рекламы, сбой у платёжного партнёра.
  7. Вывод. Гипотеза, чем её подтвердить и что предложить.

Типичная ошибка: сразу называть причину — «наверное, сезонность» — не проверив данные и не сузив область поиска.

Вопросы о коммуникации

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

Как вы презентуете результаты анализа людям без технической подготовки?

Начинаю с вывода и рекомендации, а не с методики расчёта. Структура короткая: что мы хотели узнать, что обнаружили, что это означает для бизнеса и что я предлагаю сделать. Методика и оговорки идут после — для тех, кто захочет проверить.

Несколько правил, которые стоит назвать. Один слайд или один график — одна мысль, вынесенная в заголовок целым предложением. Термины заменяю на язык слушателя: не «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–2SQL: SELECT, WHERE, GROUP BY, HAVINGСоздать таблицы из статьи, написать по памяти запросы с агрегацией, объяснить вслух порядок выполнения
3–4SQL: JOIN, NULL, подзапросы и CTEДля каждого JOIN заранее предсказать число строк; найти клиентов без заказов тремя способами
5–6SQL: оконные функцииРанжирование, накопительный итог, LAG; решить задачи 1–3 без подсказок
7Повторение SQLРешить три задачи на время, проговаривая решение вслух
8СтатистикаСвоими словами, с примером: среднее и медиана, разброс, корреляция, p-value, A/B-тест
9Excel или Google SheetsФункции поиска, сводная таблица, очистка «грязного» файла
10Power BI и DAXСобрать модель «звезда» из двух-трёх таблиц, написать меры с CALCULATE, объяснить результат
11pandas (если есть в вакансии)Прочитать файл, очистить, сгруппировать, объединить — задача 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. Будьте готовы объяснить каждое решение и каждый вывод.

Источники

Программа курса Data Analytics →

Фото автора: Елена Булыга

Об авторе

Тренер Prog Academy по Power BI, преподаватель высшей школы

Преподаватель высшей школы: преподавала компьютерные науки в НТУ и бизнес-аналитику Power BI в университете КРОК. Сотрудничает с бизнесом в сфере аналитики данных; в блоге пишет о Power BI, DAX и визуализации данных.

Контакт

Записаться на консультацию

Укажите актуальный номер, мы позвоним в любую страну :)