Как написать SQL-запрос: пошаговый пример
Что такое SQL-запрос
SQL-запрос — команда, которую вы отправляете базе данных, чтобы получить нужные данные.
Пример: «Покажи всех пользователей из Москвы».
SELECT * FROM users WHERE city = 'Moscow';Это читается как обычный текст: «выбери всё из таблицы users, где city = 'Moscow'».
Структура запроса
Любой SQL-запрос имеет до 6 основных частей:
SELECT -- что выбрать
FROM -- откуда
WHERE -- с каким фильтром
GROUP BY -- сгруппировать по
HAVING -- фильтр на группы
ORDER BY -- как сортировать
LIMIT -- сколько строкНе все части обязательны. Минимум — SELECT ... FROM ....
Пошаговый пример
Задача: «Найти топ-5 городов по выручке от заказов в апреле 2026, только города с 10+ заказами».
Шаг 1. SELECT и FROM
Начинаем с нужных полей и таблицы:
SELECT city FROM orders;Возвращает города всех заказов (с повторами).
Шаг 2. Добавляем JOIN
Выручка — в orders, города — в users. Нужно соединить:
SELECT u.city, o.amount
FROM orders o
JOIN users u ON u.user_id = o.user_id;Теперь видим пары (город, сумма).
Шаг 3. Фильтр по дате
Только апрель 2026:
SELECT u.city, o.amount
FROM orders o
JOIN users u ON u.user_id = o.user_id
WHERE o.created_at >= '2026-04-01' AND o.created_at < '2026-05-01';Шаг 4. GROUP BY
Суммируем по городам:
SELECT u.city, SUM(o.amount) AS total
FROM orders o
JOIN users u ON u.user_id = o.user_id
WHERE o.created_at >= '2026-04-01' AND o.created_at < '2026-05-01'
GROUP BY u.city;Шаг 5. HAVING
Оставляем города с 10+ заказами:
SELECT u.city, SUM(o.amount) AS total, COUNT(*) AS orders_cnt
FROM orders o
JOIN users u ON u.user_id = o.user_id
WHERE o.created_at >= '2026-04-01' AND o.created_at < '2026-05-01'
GROUP BY u.city
HAVING COUNT(*) >= 10;Шаг 6. ORDER BY + LIMIT
Сортируем по выручке, берём топ-5:
SELECT u.city, SUM(o.amount) AS total, COUNT(*) AS orders_cnt
FROM orders o
JOIN users u ON u.user_id = o.user_id
WHERE o.created_at >= '2026-04-01' AND o.created_at < '2026-05-01'
GROUP BY u.city
HAVING COUNT(*) >= 10
ORDER BY total DESC
LIMIT 5;Готово.
Больше таких примеров с разборами — в Telegram-тренажёре. Короткие сессии, прогресс по темам, объяснения после каждого ответа.
Порядок выполнения (важно!)
Хотя пишем SELECT ... FROM ... WHERE ..., СУБД выполняет в другом порядке:
- FROM + JOIN
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
- LIMIT
Отсюда:
- В WHERE нельзя использовать агрегаты (GROUP BY ещё не сделан).
- Алиасы из SELECT не всегда работают в WHERE (SELECT выполняется позже).
Советы для новичков
1. Пишите запрос постепенно
Начните с SELECT * FROM table LIMIT 10 — посмотрите, что в таблице. Добавляйте усложнения.
2. Всегда используйте alias для таблиц
FROM orders o JOIN users u ON ...Короче и читабельнее.
3. Форматируйте код
SELECT
u.city,
SUM(o.amount) AS total
FROM orders o
JOIN users u ON u.user_id = o.user_id
WHERE ...Не пишите всё одной строкой.
4. Комментируйте сложные части
-- Считаем только paid-заказы за апрель
WHERE o.status = 'paid'
AND o.created_at >= '2026-04-01'
AND o.created_at < '2026-05-01'5. Тестируйте на маленьких данных
Добавьте LIMIT 100 пока пишете — быстрее итерируете.
Типичные ошибки новичка
1. Забыть GROUP BY
-- ❌ Ошибка: city не агрегат и не в GROUP BY
SELECT city, SUM(amount) FROM orders;
-- ✅
SELECT city, SUM(amount) FROM orders GROUP BY city;2. Integer division
-- ❌ Возвращает 0, а не 0.5
SELECT 1 / 2;
-- ✅
SELECT 1.0 / 2;3. Путать WHERE и HAVING
- WHERE — фильтр строк (до группировки).
- HAVING — фильтр групп (после).
4. LEFT JOIN превращается в INNER
-- ❌ Потеряем пользователей без заказов
SELECT u.name, o.amount
FROM users u
LEFT JOIN orders o ON ...
WHERE o.status = 'paid';
-- ✅ Условие в ON, не в WHERE
SELECT u.name, o.amount
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id AND o.status = 'paid';Если готовишься к собесу — бот @kariernik_bot закрывает 80% технических вопросов. SQL, Python, A/B, продуктовые метрики — всё в одном месте.
Что учить дальше
- Оконные функции — для ранжирования, MoM, нарастающих итогов. Шпаргалка.
- CTE (WITH) — для читаемых сложных запросов. Шпаргалка.
- Подзапросы — для условий через SELECT. Шпаргалка.
- Работа с датами — DATE_TRUNC, EXTRACT. Шпаргалка.
Читайте также
FAQ
Где написать свой первый запрос?
Установите PostgreSQL + DBeaver (бесплатно). Или используйте онлайн-песочницу: SQL Fiddle, тренажёр Карьерник.
Как учить SQL?
- Базовый курс (Stepik, SQL Academy).
- 5 задач в день.
- Через 4 недели — JOIN, GROUP BY в голове.
- Через 2 месяца — оконные и CTE.
Какой SQL учить — MySQL или PostgreSQL?
Начинайте с PostgreSQL — стандартнее и функциональнее. Перейти на MySQL потом — легко, отличий мало.
Чем отличается SQL на собесе от реального?
На собесе много про «тонкости» (CASE WHEN, оконные, LEFT vs INNER). На работе — больше про понимание бизнеса и чистоту кода.