Data Scientist — не аналитик и не разработчик. SQL для него инструмент подготовки данных, а не основная специальность. Тем не менее без уверенного SQL дата-сайентист становится зависим от дата-инженеров при каждом обращении к данным.
Какой SQL нужен Data Scientist
Требования к SQL у DS отличаются от требований к аналитику данных. DS реже строит регулярные отчёты, зато чаще:
- Выгружает данные для обучения моделей
- Формирует признаки (feature engineering) через SQL
- Проверяет гипотезы на исторических данных
- Анализирует качество данных (пропуски, выбросы, дубликаты)
Для этого нужны: сложные JOIN, подзапросы, оконные функции, работа с датами, базовая статистика в SQL.
Что НЕ нужно проверять у Data Scientist
В отличие от позиции бэкенд-разработчика, DS не нужно знать:
- DDL (CREATE TABLE, ALTER TABLE) на продвинутом уровне
- Управление транзакциями
- Настройку индексов
- Детали репликации и партиционирования
Базовое понимание этих тем желательно, но не критично.
Задача 1: Подготовка обучающего датасета
-- Задача: сформируйте датасет для обучения модели оттока клиентов.
-- Нужны: customer_id, дни с последней покупки, число покупок за 90 дней,
-- средний чек, флаг оттока (нет покупок за последние 30 дней)
SELECT
c.id AS customer_id,
CURRENT_DATE - MAX(o.order_date)::DATE AS days_since_last_order,
COUNT(CASE WHEN o.order_date >= CURRENT_DATE - 90
THEN 1 END) AS orders_last_90d,
ROUND(AVG(o.amount), 2) AS avg_order_amount,
CASE WHEN MAX(o.order_date) < CURRENT_DATE - 30
THEN 1 ELSE 0 END AS is_churned
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id;
Что проверяем: сложная агрегация, работа с датами, CASE для бинарного признака.
Задача 2: Анализ качества данных
-- Задача: найдите проблемы в таблице транзакций:
-- - NULL-значения в ключевых полях
-- - дубликаты по (user_id, transaction_id)
-- - транзакции с отрицательными суммами
-- - транзакции в будущем
SELECT 'null_user_id' AS issue, COUNT(*) AS count
FROM transactions WHERE user_id IS NULL
UNION ALL
SELECT 'null_amount', COUNT(*) FROM transactions WHERE amount IS NULL
UNION ALL
SELECT 'negative_amount', COUNT(*) FROM transactions WHERE amount < 0
UNION ALL
SELECT 'future_date', COUNT(*) FROM transactions WHERE transaction_date > CURRENT_DATE
UNION ALL
SELECT 'duplicates',
COUNT(*) - COUNT(DISTINCT (user_id, transaction_id))
FROM transactions;
Что проверяем: UNION ALL для сводного отчёта, разнообразие условий фильтрации.
Задача 3: Feature Engineering с оконными функциями
-- Задача: для каждой сессии пользователя вычислите:
-- - порядковый номер сессии
-- - время с предыдущей сессии (в днях)
-- - скользящее среднее длительности за 3 сессии
SELECT
user_id,
session_date,
duration_min,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY session_date) AS session_num,
session_date - LAG(session_date) OVER (
PARTITION BY user_id ORDER BY session_date
) AS days_since_prev,
AVG(duration_min) OVER (
PARTITION BY user_id
ORDER BY session_date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS rolling_avg_3s
FROM sessions;
Что проверяем: комплексное применение оконных функций для feature engineering.
Задача 4: Сегментация по RFM
RFM (Recency, Frequency, Monetary) — базовая модель сегментации клиентов, которую DS часто реализует в SQL:
WITH rfm_raw AS (
SELECT
customer_id,
CURRENT_DATE - MAX(order_date)::DATE AS recency,
COUNT(*) AS frequency,
SUM(amount) AS monetary
FROM orders
GROUP BY customer_id
),
rfm_scored AS (
SELECT *,
NTILE(5) OVER (ORDER BY recency ASC) AS r_score, -- меньше дней = лучше
NTILE(5) OVER (ORDER BY frequency DESC) AS f_score,
NTILE(5) OVER (ORDER BY monetary DESC) AS m_score
FROM rfm_raw
)
SELECT
customer_id,
recency, frequency, monetary,
r_score, f_score, m_score,
r_score + f_score + m_score AS rfm_total
FROM rfm_scored
ORDER BY rfm_total DESC;
Что проверяем: CTE, NTILE, понимание бизнес-задачи.
Статистические функции в PostgreSQL
Для DS важно знать статистические возможности SQL:
-- Базовая статистика
SELECT
AVG(amount) AS mean,
STDDEV(amount) AS std_dev,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS median,
PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY amount) AS q1,
PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY amount) AS q3
FROM orders;
Кандидат-DS должен знать разницу между AVG и MEDIAN, понимать выбросы.
Шкала оценки для Data Scientist
| Навык | Важность | Проверка |
|---|---|---|
| Сложные JOIN (3+ таблицы) | Высокая | Задача на формирование датасета |
| Оконные функции | Высокая | Feature engineering |
| Работа с датами | Высокая | Подготовка временных признаков |
| CTE | Средняя | Структурирование сложного запроса |
| Статистические функции | Средняя | Базовая EDA через SQL |
| Оптимизация запросов | Низкая | Общее понимание |
Для DS проходной балл по SQL обычно ниже, чем для аналитика данных — при условии сильного Python/ML бэкграунда.
Кандидаты DS часто имеют пробелы именно в SQL. Порекомендуйте им SQLlab.ru для быстрого заполнения этих пробелов перед собеседованием.