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 для аналитика.

Типичные вопросы

«Как ускорить медленный дашборд?»

  1. EXPLAIN плана запроса.
  2. Materialized view на нужной grain.
  3. Composite index под фильтры.
  4. Partition pruning.
  5. Если 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 — нет.

Смотрите также