BA & SA | 10000 Interview questions
10.2K subscribers
172 photos
14 videos
342 links
Вопросы и задачи, которые задают на собеседованиях на позицию Бизнес и Системного аналитика. По вопросам сотрудничества- @DeliveryManager7
Download Telegram
4736. При интеграции с платежным сервисом система получила код 429 (Too Many Requests). Разработчик обработал его как фатальную ошибку, хотя бизнес ожидал автоматических повторов. Где возникла проблема?
Anonymous Quiz
1%
Разработчик неверно понял код ответа
9%
Тестировщик не проверил сценарий с 429
76%
Аналитик не описал поведение системы для разных HTTP-кодов
13%
Архитектор не заложил механизм retry
👍11
№4736 категория вопросов: #TESTING
🧑‍🎓Объяснение:
Это классический кейс из практики интеграций, демонстрирующий критическую важность полноты требований. Код 429 (Too Many Requests) — это стандартный сигнал от внешнего сервиса о превышении лимита запросов. В большинстве систем ожидается, что клиент автоматически повторит запрос через некоторое время (обычно с экспоненциальной задержкой).

Почему не другие варианты:

A (Разработчик) — он строго следовал ТЗ, где не было указаний по обработке 429. Если в требованиях написано «при ошибке прерывать операцию», разработчик поступил корректно.

B (Тестировщик) — тестировщик проверяет только задокументированные сценарии. Без требования сценарий с 429 не включается в тест-план.

D (Архитектор) — архитектор может предложить общий механизм повторных попыток (retry policy), но конкретные условия — какие коды должны вызывать повторы, сколько попыток делать, с какими интервалами — это зона ответственности аналитика, который описывает функциональное поведение системы.

Корень проблемы: Аналитик не заложил в требованиях обработку различных HTTP-кодов ответа от внешнего сервиса. Интеграционные сценарии часто содержат множество нюансов: временные ошибки (429, 503), требующие повтора; ошибки валидации (400), требующие корректировки данных; ошибки авторизации (401, 403), требующие обновления токена.

Что должен был сделать аналитик:

Изучить документацию внешнего сервиса и выписать все возможные коды ответа.
Для каждого кода согласовать с бизнесом ожидаемое поведение системы:
200 — успех, идём дальше.
400 — ошибка в данных, показываем пользователю, что нужно исправить.
429 — временная ошибка, автоматически повторяем до 3 раз с интервалом 5, 30, 60 секунд.
500 — ошибка сервера, повторяем 3 раза, если не успешно — уведомляем администратора.
Задокументировать это в виде понятной таблицы или матрицы решений.
Последствия отсутствия таких требований:

Разработчик принимает решение на основе своего опыта (часто ошибочного).
Тестировщик не проверяет непрописанные сценарии.
В прод уходит функционал, который не соответствует ожиданиям бизнеса.
Пользователи видят ошибки там, где могли бы быть автоматические повторы.
Вывод: Полнота требований к интеграциям — прямая ответственность аналитика. Чем детальнее прописано поведение системы во всех возможных ситуациях, тем меньше рисков на этапах разработки и тестирования. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
1
№4737 категория вопросов: #TESTING
4737. Банк обновил версию API для проверки кредитных историй. Разработчики протестировали новую версию, всё работало. Через неделю старая версия API отключилась, и система перестала выдавать кредиты. В чём первопричина?
Anonymous Quiz
13%
Разработчики не учли отключение старой версии
22%
Тестировщики не проверили сценарий без старого API
51%
Аналитик не описал требование к graceful degradation при недоступности внешнего сервиса
14%
Архитектор не заложил механизм автоматического переключения
🧑‍🎓Объяснение:

Это реальный кейс из практики интеграций. Аналитик описал только функциональность с новой версией API, но не указал, что должно происходить, если старый API отключится или новый станет недоступен. В результате команда тестировала только «прямой» сценарий, но не проверила поведение системы в момент отключения старой версии.

Почему не другие варианты:

A (Разработчики) — они реализовали поддержку новой версии, но не знали, что старая скоро отключится, и не закладывали логику переключения.

B (Тестировщики) — тестировали то, что написано в требованиях. Без требования о graceful degradation этот сценарий не включается в план тестирования.

D (Архитектор) — может предложить решение (балансировку, fallback), но только если в требованиях указана необходимость непрерывности работы.
Что должен был сделать аналитик:

При описании интеграции указать: «Система должна поддерживать обе версии API в течение переходного периода».
Прописать поведение при недоступности API (например, отложить обработку, уведомить администратора, использовать кэшированные данные).
Включить в приёмочные тесты сценарии отключения старой версии и потери связи с новой.
Вывод: Надёжность системы закладывается на уровне требований, а не обнаруживается после падения в проде. 📉
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Как находят работу за бугром в IT

Наити работу на немецком рынке. И не через релокацию! Сам нашел и сам переехал!

Это история Бизнес аналитика, который работает в Deutsche Bank и язвительно пишет из солнечного Франкфурта-на-Майне.

Из ХЗ в ТЗ — блог про работу в финтехе и как там у них. Антон также исследует рынок РФ и продолжает ходить на собеседования.

Истории, которые уже вышли:
🟢 собеседование в банк Азии на 380К. Кринж😬
🟢 красные флаги в тестовом задании. И референс ответа.
🟢 как мы делали mit den Jungs в банке
🟢 стал бы я в 2026-ом накручивать опыт в резюме?

Переходите знакомиться: @anton_alekseev
4738. Вы пишете запрос для отчета по продажам. Нужно получить список товаров, у которых общая сумма продаж превышает 100 000 рублей. Как правильно написать условие?
Anonymous Quiz
32%
WHERE SUM(sales_amount) > 100000
53%
HAVING SUM(sales_amount) > 100000
4%
FILTER SUM(sales_amount) > 100000
11%
GROUP BY с условием в SELECT
№4738 категория вопросов: #SQL
🧑‍🎓Объяснение:

Это классическая задача, где важно понимать разницу между WHERE и HAVING.

WHERE применяется до группировки (GROUP BY) и фильтрует отдельные строки таблицы.
HAVING применяется после группировки и фильтрует уже сгруппированные результаты (агрегатные функции, такие как SUM(), COUNT(), AVG()).
В вашем случае SUM(sales_amount) вычисляется после группировки по товарам, поэтому условие должно быть в HAVING. Если написать WHERE SUM(sales_amount) > 100000, СУБД выдаст ошибку, потому что на момент выполнения WHERE агрегатные функции ещё не вычислены.

Пример правильного запроса:

```sql
SELECT product_id, SUM(sales_amount) as total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 100000;
```

Почему не другие варианты:

A — WHERE не работает с агрегатными функциями.

C — FILTER существует в SQL, но это нестандартный синтаксис для агрегации (используется редко, например, в PostgreSQL для частичной агрегации), и здесь он не применим.

D — условие нельзя поместить в SELECT, потому что оно должно отсеивать целые группы, а не просто отображать значение.
Вывод для аналитика:

При работе с группированными данными всегда используйте HAVING для фильтрации по агрегатам, а WHERE оставьте для фильтрации отдельных записей до группировки. Это фундаментальное правило SQL, которое помогает избежать ошибок в отчётах и анализах. 📊
Please open Telegram to view this post
VIEW IN TELEGRAM
2🤩1
№4739 категория вопросов: #SQL
4739. Аналитик ищет клиентов без заказов: «ID клиента отсутствует в списке ID заказов». В списке ID заказов есть NULL. Что вернет запрос?
Anonymous Quiz
16%
Только клиентов без заказов
39%
Всех клиентов, кроме тех, у кого есть заказы
28%
Пустой результат (ни одного клиента)
18%
Ошибку выполнения запроса
🤔71
🧑‍🎓Объяснение:

Это классическая «ловушка NULL» в SQL. Когда в подзапросе, формирующем список идентификаторов, встречается NULL, операция «NOT IN» ведёт себя неочевидно. Из-за трёхзначной логики SQL (TRUE, FALSE, UNKNOWN) сравнение с NULL даёт UNKNOWN. Если хотя бы одно значение в списке — NULL, то для любой проверяемой строки условие никогда не станет TRUE, и запрос не вернёт ни одной записи.

Пример для понимания:
Представьте, что у нас есть клиенты с ID 1, 2, 3. В таблице заказов есть ID клиентов: 1 и NULL. Запрос мысленно проверяет каждого клиента:

Клиент 2 отсутствует в списке {1, NULL}? Сравнение с 1 даёт TRUE (2 не равно 1), но сравнение с NULL даёт UNKNOWN (2 не равно неизвестности). Итог — UNKNOWN, условие не выполняется.
Аналогично для всех клиентов — ни один не проходит.
Как избежать ошибки:

Использовать проверку через NOT EXISTS (она корректно обрабатывает NULL).
Исключить NULL из подзапроса, добавив условие WHERE customer_id IS NOT NULL.
Вывод для аналитика:

Всегда учитывайте возможность NULL в данных при написании запросов с отрицанием. Это частая причина некорректных отчётов и потери данных. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
2
4740. Вы проектируете таблицу для хранения действий пользователей. Прогноз: 10 млн записей в день. Самый частый запрос: «показать все действия конкретного пользователя за последние 30 дней». Как обеспечить максимальную производительность?
Anonymous Quiz
23%
Создать составной индекс (user_id, action_time) в одной таблице.
56%
Партиционировать таблицу по месяцам и создать локальный индекс по user_id.
13%
Хранить действия каждого пользователя в отдельном JSON-документе в MongoDB.
9%
Шардировать таблицу по user_id на несколько физических серверов.
№4740 категория вопросов: #DBMS
🧑‍🎓Объяснение:
1. Масштаб проблемы и математика

10 млн записей в день → ≈ 300 млн записей в месяц, ≈ 3.6 млрд в год.
Типичная строка лога: user_id (8 байт) + action_time (8 байт) + action_type (2 байта) + details (переменная). Оценим средний размер строки в 100 байт.
Размер таблицы за месяц: 300 млн × 100 байт = 30 ГБ.
Размер за год: 360 ГБ (без учёта индексов и накладных расходов).
Индекс на (user_id, action_time) в такой таблице займёт не менее 20–30% от объёма данных (B-дерево, ссылки на строки). Это ещё + 100 ГБ через год.
Запрос «за последние 30 дней» будет читать 1/12 часть от годового объёма (если нет партиционирования). Но даже чтение 30 ГБ с диска — это секунды или минуты, даже при полном сканировании индекса. Однако проблема не только в объёме, но и в структуре доступа.

2. Почему вариант A (просто индекс) не спасёт

Индекс (user_id, action_time) ускоряет поиск по конкретному пользователю, но данные в таблице физически разбросаны по всей её территории (записи вставляются в хронологическом порядке, но для одного пользователя они распределены по всем блокам).
Чтобы получить все действия пользователя за 30 дней, СУБД должна:
Найти в индексе все записи для этого user_id за указанный период (это быстро).
Выполнить случайные чтения (random I/O) каждой строки из таблицы по указателям из индекса. При большом количестве строк (например, у активного пользователя 1000 действий за месяц) это приведёт к тысячам случайных обращений к диску.
Даже если используется covering index (включить все нужные поля в индекс), то индекс сам по себе станет огромным и его сканирование за 30 дней всё равно потребует чтения миллионов записей индекса.
Индекс не решает проблему устаревания данных: удаление старых записей (например, через год) потребует тяжёлого DELETE с блокировками и фрагментацией.
3. Почему партиционирование (вариант B) — оптимальное решение

Партиционирование по диапазону дат (например, по месяцам) — стандартный паттерн для временных рядов. Оно даёт:

Partition Pruning (отсечение партиций)

Планировщик запроса понимает, что условие action_time BETWEEN ... AND ... затрагивает только определённые партиции (например, текущий и предыдущий месяц). Он не будет сканировать остальные партиции с данными за прошлые годы. Вместо 360 ГБ читается максимум 30–60 ГБ (1–2 партиции).

Локальные индексы

Индекс по user_id внутри каждой партиции имеет гораздо меньшую высоту B-дерева (т.к. работает с 30 млн строк, а не с 3.6 млрд). Это ускоряет поиск и снижает потребление памяти.

Управление жизненным циклом данных
Удаление старых данных — это DROP PARTITION, а не DELETE. Операция занимает миллисекунды и не вызывает фрагментации.
Архивация: партицию можно быстро отсоединить от таблицы (DETACH PARTITION) и сохранить как отдельную таблицу или файл.
Обслуживание (реиндексация, анализ) можно проводить на отдельных партициях, не блокируя всю таблицу.

Производительность записи

Записи распределяются по партициям в соответствии с датой. Это не создаёт «горячих точек» (hotspots) — вставки идут в текущую партицию, но это нормально. Если нужно распределить нагрузку ещё сильнее, можно использовать субпартиционирование (например, по дням или по хешу user_id внутри месяца).

4. Почему MongoDB (вариант C) — не лучший выбор

Ограничение размера документа: BSON-документ не может превышать 16 МБ. У активного пользователя за несколько лет действий может накопиться гораздо больше (даже за месяц — тысячи событий, JSON с ними легко превысит 16 МБ).
Запросы внутри документа: Если хранить все действия в массиве, то выборка за последние 30 дней потребует разбора всего массива и фильтрации на стороне приложения — это неэффективно и нагружает сеть.
Индексирование: MongoDB поддерживает индексы на полях вложенных массивов, но при частых обновлениях документа (добавлении нового действия) происходит перезапись всего документа — это дорого и вызывает фрагментацию.
Транзакционность: Если нужны транзакции или сложные joins (например, с пользователями), MongoDB не подходит.
Когда MongoDB хороша: для редких изменений и чтения всего документа целиком.
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Продолжение к объяснению ❗️

5. Почему шардинг по user_id (вариант D) неэффективен для этого запроса

Шардинг (горизонтальное масштабирование) распределяет данные по физическим узлам на основе ключа (например, user_id).
Запрос «действия за последние 30 дней» не ограничен по ключу шардирования — он требует данные за определённый период, но у разных пользователей эти данные лежат на разных узлах.
Придётся выполнить запрос ко всем шардам (fan-out), собрать результаты и отсортировать. Это создаёт огромную сетевую нагрузку и задержки.
Шардинг полезен, когда все запросы содержат ключ шардирования (например, «показать действия пользователя X»). Но в нашем случае запрос включает ещё и период, поэтому шардинг по user_id не даст partition pruning по времени.
Шардинг требует дополнительной инфраструктуры (маршрутизаторы, балансировка) и усложняет операции JOIN и транзакции.
Когда шардинг оправдан: если данные не имеют естественного временного разреза и запросы всегда содержат ключ шардирования (например, социальная сеть: все посты пользователя).

6. Дополнительные рекомендации для аналитика

При проектировании таблиц с временными метками всегда задавайте вопрос: «Какой объём данных будет накоплен через год? Через три года?»
Партиционирование должно быть заложено в требования к физической модели данных с самого начала. Это не оптимизация постфактум — добавить партиционирование на таблицу с миллиардами строк очень трудоёмко.
Выбирайте ключ партиционирования так, чтобы он совпадал с условиями в самых частых запросах (здесь — action_time).
Рассмотрите интервал партиционирования (день, неделя, месяц) в зависимости от частоты запросов и скорости роста.
Не забывайте про локальные vs глобальные индексы: в большинстве СУБД (PostgreSQL, Oracle, MySQL) локальные индексы автоматически партицируются вместе с таблицей и обслуживаются независимо.
Учитывайте операции обслуживания: партиционирование позволяет делать VACUUM, ANALYZE, REINDEX на отдельных партициях без простоя всей системы.
Для ещё большей производительности можно комбинировать партиционирование с кластеризацией (физической сортировкой данных внутри партиции по user_id), но это требует дополнительного планирования.

7. Итог

Партиционирование по времени с локальными индексами — единственный вариант, который одновременно:

сокращает объём сканируемых данных (partition pruning),
обеспечивает быстрый доступ по пользователю (локальный индекс),
упрощает обслуживание и удаление старых данных (DROP PARTITION),
масштабируется горизонтально без усложнения инфраструктуры.
Это промышленный стандарт для систем с временными рядами (логи, события, метрики). Системный аналитик, закладывающий такое решение на этапе проектирования, предотвращает будущие проблемы с производительностью и стоимостью владения системой. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
№4741 категория вопросов: #REQUIREMENTS
4741. ва руководителя в банке спорят о дизайне главного экрана личного кабинета. Один требует «максимум информации», второй — «только самое нужное». Сроки горят, бюджет ограничен. Что делать аналитику?
Anonymous Quiz
8%
Найти средний вариант и утвердить у обоих
78%
Провести совместный воркшоп, чтобы согласовать приоритеты
12%
Сделать настраиваемый интерфейс под каждого пользователя
1%
Передать решение архитектору
🧑‍🎓Объяснение:

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

1. Почему это реальный кейс?

В крупных проектах (банки, ритейл, телеком) разные отделы преследуют свои цели:

Кредитный отдел хочет увеличить выдачу кредитов → нужна информация о лимитах, предложениях, задолженностях на виду.
Отдел депозитов заботится о привлечении средств → нужны ставки, остатки, условия.
Маркетинг хочет промо-акции.
Безопасность требует ограничить видимость чувствительных данных.
Аналитик оказывается между молотом и наковальней. Просто «усреднить» требования (вариант A) — значит, скорее всего, не удовлетворить никого. Кастомизация (C) — дорого и долго, а бюджет фиксирован. Передать архитектору (D) — значит, снять с себя ответственность, но техническое решение не заменит бизнес-согласования.

2. Почему воркшоп с фасилитацией (B) — единственно верный путь?

Цель: перевести эмоциональные требования («хочу много / хочу мало») в измеримые и объективные критерии, а затем согласовать приоритеты.

Этапы воркшопа:

Подготовка:
Собрать все противоречивые требования заранее.
Определить критерии оценки (например: влияние на конверсию, затраты на разработку, риски, соответствие стратегии).
Пригласить обоих стейкхолдеров + фасилитатора (лучше нейтрального, можно внешнего).
Выявление истинных потребностей (техника «5 почему»):
«Почему вам нужна максимальная информация?» → «Чтобы клиент сразу видел, что может взять кредит» → истинная потребность: повышение конверсии в кредиты.
«Почему вы хотите минимум информации?» → «Клиенты жалуются на сложность интерфейса» → истинная потребность: удобство и снижение оттока.
Перевод в измеримые цели:
«Увеличить конверсию в кредиты на 15%».
«Снизить количество обращений в поддержку по навигации на 20%».
Поиск вариантов решения, удовлетворяющих обе цели:
Например, умный дашборд, который показывает разный набор виджетов в зависимости от сегмента клиента (активные кредиты — видит кредитную информацию, вкладчики — депозитную).
Или поэтапный подход: сначала MVP с ограниченным набором, но с возможностью быстрого A/B-тестирования гипотез.
Приоритизация (MoSCoW или Weighted Scoring):
Оцениваем каждую «фичу» по влиянию на цели и стоимости.
Стейкхолдеры видят объективную картину и договариваются, что важнее сделать сейчас, а что отложить.
Фиксация договорённостей:
Протокол с чёткими решениями, подписанный обоими руководителями.

3. Инструменты фасилитации для такого конфликта

Impact Mapping: связать требования с бизнес-целями.
User Story Mapping: увидеть, как фичи вписываются в пользовательский путь.
Kano Model: классифицировать требования на базовые, линейные и «восхитители».
Weighted Shortest Job First (WSJF): приоритизация по ценности и срочности.

4. Роль аналитика в этом процессе

Аналитик не должен становиться «третьей стороной», которая выбирает между стейкхолдерами. Его задача:

Фасилитировать диалог, а не принимать решения за бизнес.
Переводить эмоции в факты (цифры, исследования, метрики).
Предлагать варианты (не «или-или», а «и то, и другое, но с ограничениями»).
Документировать компромиссы и обоснования для будущих изменений.

5. Почему другие варианты не работают в долгосрочной перспективе

A (компромисс): Половинчатое решение часто не удовлетворяет ни одну из сторон. Через месяц начнутся новые споры, требования изменятся, разработка пойдёт по кругу.

C (кастомизация): Технически сложно и дорого. Кроме того, интерфейс, настраиваемый пользователем, требует собственного UX-исследования и поддержки. При фиксированном бюджете это убьёт проект.

D (передать архитектору): Архитектор спроектирует технически красивое решение, но оно не решит бизнес-конфликт. Техническая реализация не заменяет согласования целей.

6. Что делать, если воркшоп не помог?

Бывает, что стейкхолдеры не готовы договариваться. Тогда аналитик должен:

Поднять вопрос на уровень выше (спонсор проекта, продуктовый комитет).
Предложить A/B-тест (если позволяет время и бюджет)— пусть данные покажут
Please open Telegram to view this post
VIEW IN TELEGRAM
Продолжение к объяснению❗️

Что лучше для бизнеса.
Задокументировать риски (например, «если не договоримся, срыв сроков с вероятностью 80%»).

7. Профессиональный вывод

Умение управлять конфликтами стейкхолдеров — один из ключевых навыков системного аналитика высокого уровня. Техническая часть (написать ТЗ) — это только вершина айсберга. Основа — выявление истинных потребностей, фасилитация и принятие взвешенных решений в условиях неопределённости. Именно такие кейсы отделяют senior-аналитика от middle.

Итог: Воркшоп с фасилитацией — не просто «поговорить», а структурированный процесс, который превращает конфликт в конструктивное решение, экономя время и бюджет проекта. 🎯
Please open Telegram to view this post
VIEW IN TELEGRAM