SQLLab
Все статьи

SQL для аналитика данных: что нужно знать в 2026 году

Какой SQL нужен аналитику данных: от базовых SELECT до оконных функций и оптимизации. Реальные задачи из аналитики с примерами запросов.

15 марта 2026 г.·4 мин чтения·

SQL — главный инструмент аналитика данных. Не Python, не Excel — именно SQL. По данным опросов, 80% аналитиков используют SQL ежедневно. В этой статье — что конкретно нужно знать, с реальными примерами задач.

Уровень 1: базовый SELECT (без него никуда)

Начнём с основ, которые нужны всегда.

-- Выборка с фильтрацией и сортировкой
SELECT
  user_id,
  order_date,
  amount,
  status
FROM orders
WHERE status = 'paid'
  AND order_date >= '2026-01-01'
ORDER BY amount DESC
LIMIT 100;

Что нужно знать твёрдо:

  • WHERE с несколькими условиями (AND, OR, NOT, IN, BETWEEN, LIKE)
  • ORDER BY + LIMIT / OFFSET
  • DISTINCT для уникальных значений
  • Работа с NULL: IS NULL, COALESCE

Уровень 2: агрегация — основа аналитики

90% аналитических задач сводятся к «посчитать что-то по группам».

-- Классическая задача: метрики по когортам
SELECT
  DATE_TRUNC('month', created_at)  AS cohort_month,
  COUNT(DISTINCT user_id)          AS new_users,
  SUM(amount)                      AS revenue,
  AVG(amount)                      AS avg_order,
  COUNT(*)                         AS orders_count
FROM orders
WHERE status = 'paid'
GROUP BY DATE_TRUNC('month', created_at)
ORDER BY cohort_month;

Типичные аналитические задачи:

-- Конверсия по источникам трафика
SELECT
  source,
  COUNT(DISTINCT session_id)                  AS sessions,
  COUNT(DISTINCT CASE WHEN converted THEN user_id END) AS conversions,
  ROUND(
    100.0 * COUNT(DISTINCT CASE WHEN converted THEN user_id END)
    / NULLIF(COUNT(DISTINCT session_id), 0),
    2
  ) AS conversion_rate_pct
FROM sessions
GROUP BY source
ORDER BY sessions DESC;

Уровень 3: JOIN — соединять данные из нескольких таблиц

В реальной аналитике данные всегда разбиты по таблицам.

-- LTV пользователя: выручка за всё время
SELECT
  u.id,
  u.email,
  u.created_at                     AS registration_date,
  COUNT(o.id)                      AS total_orders,
  COALESCE(SUM(o.amount), 0)       AS ltv,
  MAX(o.created_at)                AS last_order_date
FROM users u
LEFT JOIN orders o ON o.user_id = u.id AND o.status = 'paid'
GROUP BY u.id, u.email, u.created_at
ORDER BY ltv DESC;

LEFT JOIN вместо INNER JOIN — чтобы пользователи без заказов тоже попали в отчёт с LTV = 0.


Уровень 4: оконные функции — продвинутая аналитика

Без оконных функций невозможно делать retention, когортный анализ, ранжирование.

-- Retention: вернулся ли пользователь на следующей неделе
WITH weekly_activity AS (
  SELECT
    user_id,
    DATE_TRUNC('week', event_date) AS week
  FROM events
  GROUP BY user_id, DATE_TRUNC('week', event_date)
),
retention AS (
  SELECT
    w1.week                                AS cohort_week,
    COUNT(DISTINCT w1.user_id)             AS users,
    COUNT(DISTINCT w2.user_id)             AS retained
  FROM weekly_activity w1
  LEFT JOIN weekly_activity w2
    ON w1.user_id = w2.user_id
    AND w2.week = w1.week + INTERVAL '1 week'
  GROUP BY w1.week
)
SELECT
  cohort_week,
  users,
  retained,
  ROUND(100.0 * retained / NULLIF(users, 0), 1) AS retention_pct
FROM retention
ORDER BY cohort_week;
-- Топ-3 продукта по выручке в каждой категории
SELECT category, product_name, revenue
FROM (
  SELECT
    category,
    product_name,
    SUM(amount) AS revenue,
    ROW_NUMBER() OVER (
      PARTITION BY category
      ORDER BY SUM(amount) DESC
    ) AS rn
  FROM order_items oi
  JOIN products p ON p.id = oi.product_id
  GROUP BY category, product_name
) t
WHERE rn <= 3;

Уровень 5: CTE для сложных отчётов

Сложный отчёт — это несколько шагов. CTE делает это читаемым.

-- Воронка продаж
WITH
funnel_steps AS (
  SELECT
    user_id,
    MAX(CASE WHEN event = 'page_view'      THEN 1 ELSE 0 END) AS visited,
    MAX(CASE WHEN event = 'add_to_cart'    THEN 1 ELSE 0 END) AS added,
    MAX(CASE WHEN event = 'checkout_start' THEN 1 ELSE 0 END) AS checkout,
    MAX(CASE WHEN event = 'purchase'       THEN 1 ELSE 0 END) AS purchased
  FROM events
  WHERE event_date >= CURRENT_DATE - 30
  GROUP BY user_id
)
SELECT
  SUM(visited)   AS step1_visited,
  SUM(added)     AS step2_added_to_cart,
  SUM(checkout)  AS step3_checkout,
  SUM(purchased) AS step4_purchased,
  ROUND(100.0 * SUM(added)     / NULLIF(SUM(visited),   0), 1) AS s1_to_s2,
  ROUND(100.0 * SUM(checkout)  / NULLIF(SUM(added),     0), 1) AS s2_to_s3,
  ROUND(100.0 * SUM(purchased) / NULLIF(SUM(checkout),  0), 1) AS s3_to_s4
FROM funnel_steps;

Реальные задачи с собеседований

На собеседованиях аналитиков чаще всего просят:

1. Найти пользователей, не вернувшихся после первого заказа

SELECT user_id
FROM orders
GROUP BY user_id
HAVING COUNT(*) = 1;

2. Скользящее среднее за 7 дней

SELECT
  order_date,
  revenue,
  AVG(revenue) OVER (
    ORDER BY order_date
    ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
  ) AS rolling_7d_avg
FROM daily_revenue;

3. Доля каждого продукта в выручке категории

SELECT
  category,
  product_name,
  revenue,
  ROUND(
    100.0 * revenue / SUM(revenue) OVER (PARTITION BY category),
    1
  ) AS pct_of_category
FROM product_revenue
ORDER BY category, revenue DESC;

Чек-лист аналитика

ТемаНужно уметь
SELECT / WHERE / ORDERБазовая фильтрация и сортировка
GROUP BY + агрегатыCOUNT, SUM, AVG, MIN/MAX, HAVING
JOININNER, LEFT; поиск «сирот» через IS NULL
Оконные функцииROW_NUMBER, RANK, LAG/LEAD, SUM OVER
CTEWITH, вложенные CTE, рекурсия
ДатыDATE_TRUNC, EXTRACT, INTERVAL, AGE
NULLCOALESCE, NULLIF, IS NULL
ПодзапросыEXISTS, IN, коррелированные

Хочешь прокачать SQL для аналитики? В нашем тренажёре — задачи уровня Яндекс и Ozon, от простых до сложных. Без установки, сразу в браузере.

Похожие статьи

Попробуй на практике

Тренажёр с реальными задачами — бесплатно и без регистрации

Открыть тренажёр →