Задачи по SQL для junior-аналитика
Что ждут от junior
На собеседовании junior-аналитика проверяют:
- SELECT, WHERE, ORDER BY — уверенно.
- JOIN INNER/LEFT — без путаницы.
- GROUP BY + агрегаты.
- HAVING.
- Базовые подзапросы.
- Простые оконные (ROW_NUMBER).
Ниже 15 реальных задач junior-уровня.
Схема данных
Во всех задачах три таблицы:
users (user_id, name, city, registered_at)products (product_id, name, category, price)orders (order_id, user_id, product_id, amount, created_at)
1. Топ-10 самых активных пользователей
Найдите 10 пользователей с наибольшим количеством заказов.
SELECT u.name, COUNT(o.order_id) AS orders_count
FROM users u
JOIN orders o USING (user_id)
GROUP BY u.user_id, u.name
ORDER BY orders_count DESC
LIMIT 10;2. Суммарные продажи по городам
SELECT u.city, SUM(o.amount) AS total_sales
FROM users u
JOIN orders o USING (user_id)
GROUP BY u.city
ORDER BY total_sales DESC;3. Пользователи без заказов
SELECT u.*
FROM users u
LEFT JOIN orders o USING (user_id)
WHERE o.order_id IS NULL;4. Средний чек в каждом городе
SELECT u.city, AVG(o.amount) AS avg_check
FROM users u
JOIN orders o USING (user_id)
GROUP BY u.city
ORDER BY avg_check DESC;5. Товары, которые никто не купил
SELECT p.*
FROM products p
LEFT JOIN orders o USING (product_id)
WHERE o.order_id IS NULL;Тренироваться на таких вопросах можно в Telegram-боте Карьерник — там 1500+ задач с реальных собесов с разборами.
6. Количество заказов по месяцам
SELECT DATE_TRUNC('month', created_at) AS month, COUNT(*) AS orders
FROM orders
GROUP BY DATE_TRUNC('month', created_at)
ORDER BY month;7. Категории с выручкой больше 1М
SELECT p.category, SUM(o.amount) AS revenue
FROM products p
JOIN orders o USING (product_id)
GROUP BY p.category
HAVING SUM(o.amount) > 1000000;8. Первый заказ каждого пользователя
SELECT user_id, MIN(created_at) AS first_order
FROM orders
GROUP BY user_id;9. Второй способ — через ROW_NUMBER
WITH ranked AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at) AS rn
FROM orders
)
SELECT * FROM ranked WHERE rn = 1;Чем отличается от предыдущей: возвращает всю строку заказа, не только дату.
10. Пользователи с заказами в марте И апреле 2026
SELECT user_id
FROM orders
WHERE created_at >= '2026-03-01' AND created_at < '2026-05-01'
GROUP BY user_id
HAVING COUNT(DISTINCT DATE_TRUNC('month', created_at)) = 2;11. Топ-1 товар в каждой категории
WITH ranked AS (
SELECT p.category, p.product_id, SUM(o.amount) AS revenue,
ROW_NUMBER() OVER (PARTITION BY p.category ORDER BY SUM(o.amount) DESC) AS rn
FROM products p
JOIN orders o USING (product_id)
GROUP BY p.category, p.product_id
)
SELECT * FROM ranked WHERE rn = 1;12. Процент заказов со средним чеком выше 1000
SELECT
COUNT(CASE WHEN amount > 1000 THEN 1 END) * 100.0 / COUNT(*) AS pct
FROM orders;Или через FILTER (PostgreSQL):
SELECT COUNT(*) FILTER (WHERE amount > 1000) * 100.0 / COUNT(*) AS pct
FROM orders;К слову, набить руку на таких кейсах удобно через тренажёр в Telegram — разбирайте по 10 вопросов в день, через 2 недели тема становится рефлексом.
13. Пользователи, сделавшие ≥5 заказов
SELECT u.name, COUNT(o.order_id) AS cnt
FROM users u
JOIN orders o USING (user_id)
GROUP BY u.user_id, u.name
HAVING COUNT(o.order_id) >= 5
ORDER BY cnt DESC;14. Ежедневная выручка с нарастающим итогом
SELECT
created_at::DATE AS day,
SUM(amount) AS daily,
SUM(SUM(amount)) OVER (ORDER BY created_at::DATE) AS cumulative
FROM orders
GROUP BY created_at::DATE
ORDER BY day;15. Клиенты, которые купили все три товара A, B, C
SELECT user_id
FROM orders
WHERE product_id IN ('A', 'B', 'C')
GROUP BY user_id
HAVING COUNT(DISTINCT product_id) = 3;Что junior делает не так
- Забывает GROUP BY. Если в SELECT есть агрегат и поле — поле должно быть в GROUP BY.
- WHERE на агрегате. Агрегат в WHERE — ошибка, используйте HAVING.
- Integer division.
3/2 = 1, не1.5. Используйте3.0/2илиCAST(3 AS NUMERIC)/2. - NOT IN с NULL. Если подзапрос содержит NULL, NOT IN вернёт 0 строк.
- LEFT JOIN + WHERE на правой таблице. Превращает LEFT в INNER.
Как тренироваться
Решайте 3-5 задач в день в течение 2-3 недель. Тренажёр Карьерник содержит 200+ задач разного уровня с разборами.
Совет: на собесе, прежде чем писать код, проговорите логику вслух. «Мне нужно сгруппировать по городу, посчитать сумму, отсортировать по убыванию» — интервьюер оценит даже до того, как вы напишите первую строку.
Читайте также
- Задачи на JOIN
- Задачи на оконные функции
- Задачи на SQL (общее)
- Задачи по SQL для middle
- Собеседование junior-аналитик
FAQ
Сколько SQL задач нужно решить до собеса?
Junior — 100-150 задач разного уровня. За 3-4 недели это реально.
Что делать, если не знаю синтаксис?
На junior-собесе интервьюер часто подсказывает. Главное — чёткая логика и чистый псевдокод. Синтаксис доучите потом.
Нужно ли оконные функции для junior?
Базовые (ROW_NUMBER) — да. LAG, LEAD, SUM OVER — плюс, но не обязательно.
Что такое «junior-уровень» SQL?
SELECT, WHERE, ORDER BY, JOIN (INNER, LEFT), GROUP BY + агрегаты, HAVING, подзапросы, базовые оконные. Оконные функции с ROWS BETWEEN, рекурсивные CTE — middle.