SQL для BI-разработчика на собеседовании
Зачем SQL на собесе BI-разработчика
SQL — главный навык BI-разработчика. Дашборд = SQL-запрос + визуализация. Сколько умеешь в SQL — настолько хорошие дашборды делаешь. На собесе BI-разработчика SQL спрашивают глубоко: window functions, оптимизация, моделирование агрегатов.
Слабый ответ — «select-from-where». Сильный — оптимизация под дашборды (materialized views, индексы), знание difference между OLTP и OLAP БД, оптимизация джойнов на больших таблицах.
Window functions
Самая частая тема на собесе BI.
ROW_NUMBER / RANK / DENSE_RANK:
SELECT user_id, order_date,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date) AS order_seq
FROM orders;LAG / LEAD для расчёта изменения от прошлого периода:
SELECT DATE, revenue,
LAG(revenue) OVER (ORDER BY DATE) AS prev_revenue,
revenue - LAG(revenue) OVER (ORDER BY DATE) AS delta
FROM daily_revenue;SUM / AVG OVER для running totals и moving averages:
SUM(revenue) OVER (ORDER BY DATE ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS revenue_7d_maПодробнее — оконные функции — шпаргалка, LAG, LEAD в SQL.
CTE и подзапросы
CTE (WITH ...) для читаемых сложных запросов.
WITH monthly_revenue AS (
SELECT DATE_TRUNC('month', order_date) AS month,
SUM(amount) AS revenue
FROM orders
GROUP BY 1
),
growth AS (
SELECT month, revenue,
revenue / LAG(revenue) OVER (ORDER BY month) - 1 AS mom_growth
FROM monthly_revenue
)
SELECT * FROM growth WHERE month >= '2026-01-01';Рекурсивные CTE — для иерархий (например, оргструктура):
WITH RECURSIVE org AS (
SELECT employee_id, manager_id, 1 AS level
FROM employees WHERE manager_id IS NULL
UNION ALL
SELECT e.employee_id, e.manager_id, o.level + 1
FROM employees e JOIN org o ON e.manager_id = o.employee_id
)
SELECT * FROM org;Подробнее — CTE и подзапросы.
Aggregates и группировка
BI дашборд — это всегда aggregations.
GROUP BY + ROLLUP / CUBE:
SELECT region, product, SUM(revenue)
FROM sales
GROUP BY ROLLUP(region, product);FILTER (conditional aggregates):
SELECT
COUNT(*) FILTER (WHERE status = 'paid') AS paid_orders,
COUNT(*) FILTER (WHERE status = 'refunded') AS refunded_orders
FROM orders;Оптимизация под дашборды
Дашборд должен загружаться < 5 секунд. SQL-оптимизация — ключ.
Materialized views:
- Pre-aggregate данные на нужной grain (день / неделя / месяц)
- Обновляются по schedule (раз в час / день)
- Дашборд читает из MV → быстро
CREATE MATERIALIZED VIEW daily_sales AS
SELECT DATE_TRUNC('day', order_date) AS day,
region, SUM(amount) AS revenue, COUNT(*) AS orders
FROM orders
GROUP BY 1, 2;
REFRESH MATERIALIZED VIEW daily_sales;Подробнее — materialized views в SQL.
Индексы:
- Composite indexes под фильтры дашборда
- Partial indexes для типичных WHERE
- В ClickHouse — primary key и projections
Partitioning:
- По времени для time-series данных
- Pruning при фильтрах по дате
OLTP vs OLAP
OLTP (PostgreSQL, MySQL): row-store, optimized для transactional load. BI-запросы медленные.
OLAP (ClickHouse, BigQuery, Snowflake): column-store, optimized для analytics. BI-запросы быстрые.
В современных компаниях:
- OLTP — для операционных систем
- CDC / ETL переносит данные в OLAP (DWH / lakehouse)
- BI-дашборды читают из OLAP
Подробнее — ClickHouse vs PostgreSQL для аналитика.
Типичные вопросы
«Как ускорить медленный дашборд?»
- EXPLAIN плана запроса.
- Materialized view на нужной grain.
- Composite index под фильтры.
- Partition pruning.
- Если OLTP — мигрировать в OLAP.
«Window function vs GROUP BY?»
GROUP BY collapses rows (одна строка на группу). Window — добавляет колонку к каждой строке. Например, «средний revenue по сегменту в той же строке» — window.
«Cohort retention в SQL?»
User cohort = месяц первого визита. Считаем, какие user-cohorts активны в последующие месяцы. Window-friendly или self-join.
«Дубликаты в источнике — как handle?»
ROW_NUMBER() OVER (PARTITION BY natural_key ORDER BY updated_at DESC) → keep rn = 1. Стандарт.
Частые ошибки
- SELECT * в дашборде. Тянет ненужные колонки → медленно.
- JOIN без индексов. На больших таблицах катастрофа.
- GROUP BY до фильтрации. Сначала WHERE, потом GROUP BY.
- Без materialized views. Каждый refresh дашборда — full scan.
- Игнор EXPLAIN. Без анализа плана — слепая оптимизация.
FAQ
Какие SQL-диалекты должны знать BI?
ANSI SQL обязательно. PostgreSQL / ClickHouse / Snowflake — в зависимости от целевой компании. Различия минимальны для базовых запросов.
dbt нужен?
Желательно. В 2026 dbt — стандарт modern data stack. Знание dbt-models, tests, документации — плюс.
Как организовать SQL-код дашборда?
Через CTE для читаемости. Лучше — через dbt-модели (versioned, tested, documented).
Большая таблица — как querying?
Partitioning + clustering + materialized views. Без них на 1B+ строках любая агрегация падает.
Window functions — есть в каждой БД?
PostgreSQL, MySQL 8+, ClickHouse, BigQuery, Snowflake — да. Legacy MySQL < 8 — нет.