SQL: полный путеводитель — от первых запросов до оконных функций
От первого SELECT до оконных функций, транзакций ACID и защиты от инъекций — всё, что нужно знать об SQL, в одном навигационном гайде с примерами кода.
SQL (Structured Query Language) — язык запросов для работы с реляционными базами данных, который появился больше 50 лет назад и остаётся одним из самых востребованных навыков в IT. По данным Stack Overflow Developer Survey 2024, SQL стабильно входит в тройку самых используемых языков — его применяют бэкендеры, аналитики данных, дата-инженеры и тестировщики.
Этот путеводитель — не просто список ссылок. Каждая секция содержит самостоятельный разбор темы: от истории SQL и принципов работы реляционных баз до транзакций, нормализации и защиты от инъекций. Там, где тема заслуживает глубокого погружения, мы даём ссылку на отдельную статью. Цель — дать полную карту знаний, по которой можно выстроить обучение от нуля до уверенного уровня.
Ключевые выводы
— SQL — фундаментальный навык для любого, кто работает с данными: от джуна до архитектора
— Основные команды (SELECT, JOIN, GROUP BY) покрывают 80% повседневных задач
— Порядок выполнения запроса (FROM → WHERE → GROUP BY → SELECT) — ключ к пониманию SQL
— Транзакции, ACID и уровни изоляции гарантируют надёжность данных
— Оконные функции, CTE и хранимые процедуры — продвинутый уровень для карьерного роста
— PostgreSQL — СУБД №1 в 2024 по Stack Overflow Survey, обогнавшая MySQL
— SQL не устареет: стандарт развивается, появляются JSON-запросы и графовый SQL
Что такое SQL и зачем его учить
SQL (Structured Query Language) — декларативный язык для работы с реляционными базами данных. «Декларативный» означает, что вы описываете что хотите получить, а не как это сделать. Вы пишете «дай мне все заказы за март», а СУБД сама решает, в каком порядке обходить таблицы и какие индексы использовать.
Краткая история: в 1970 году Эдгар Кодд из IBM опубликовал реляционную модель данных. В 1974 Дональд Чемберлин и Рэймонд Бойс создали язык SEQUEL (Structured English Query Language) для работы с этой моделью. Позже его переименовали в SQL из-за торговой марки. В 1986 году ANSI принял SQL как стандарт, а последняя версия — SQL:2023 — добавила поддержку JSON и графовых запросов.
Его используют бэкендеры, аналитики, дата-инженеры и даже тестировщики. И в обозримом будущем SQL никуда не денется — язык продолжает развиваться вместе со стандартом.
Как работает SQL: от запроса до результата
Когда вы отправляете SQL-запрос, внутри СУБД происходит цепочка шагов:
- Парсинг — СУБД разбирает текст запроса, проверяет синтаксис и строит дерево разбора
- Анализ — проверяет, существуют ли таблицы и столбцы, есть ли у пользователя права доступа
- Оптимизация — самый важный этап. Оптимизатор строит несколько вариантов плана выполнения и выбирает самый дешёвый по стоимости (I/O, CPU, память)
- Выполнение — движок исполняет выбранный план: сканирует таблицы, применяет фильтры, объединяет результаты
- Возврат результата — СУБД формирует набор строк и отправляет клиенту
Логический порядок выполнения запроса
SQL-запрос пишется в одном порядке, а выполняется в другом. Вот реальная последовательность обработки:
FROM/JOIN— определяется источник данных, выполняются соединенияWHERE— фильтрация строк (до группировки)GROUP BY— группировкаHAVING— фильтрация групп (после группировки)WINDOW— вычисление оконных функцийSELECT— выбор столбцов, вычисление выражений и алиасовDISTINCT— удаление дублейORDER BY— сортировка (по стандарту SQL единственное место, где гарантированно работает алиас из SELECT (в PostgreSQL и MySQL алиасы также работают в GROUP BY))LIMIT/OFFSET— ограничение количества строк
Из-за этого порядка нельзя использовать алиас из SELECT в WHERE — на момент фильтрации SELECT ещё не выполнен. А HAVING работает после GROUP BY, поэтому в нём доступны агрегатные функции.
Именно благодаря оптимизатору SQL остаётся эффективным: вы пишете простой запрос, а СУБД сама выбирает, использовать ли индекс, в каком порядке объединять таблицы, нужна ли сортировка. Увидеть план выполнения можно командой EXPLAIN ANALYZE — это один из главных инструментов оптимизации.
Основные команды SQL
Любое знакомство с SQL начинается с четвёрки CRUD: SELECT (чтение), INSERT (создание), UPDATE (изменение), DELETE (удаление). К ним добавляются DDL-команды для управления структурой: CREATE TABLE, ALTER TABLE, DROP TABLE, TRUNCATE TABLE (быстрое удаление всех строк без логирования каждой).
Реальная мощь SQL раскрывается в объединениях через JOIN (INNER, LEFT, RIGHT, FULL), группировке с GROUP BY и фильтрации агрегатов через HAVING. Пример: найти средний чек по городам, где было больше 100 заказов: А также CROSS JOIN (декартово произведение всех строк) и SELF JOIN (соединение таблицы с собой — например, для поиска сотрудников и их руководителей).
На практике эти команды покрывают примерно 80% задач. Полный разбор с примерами — в нашем гайде по основным командам SQL. Статью прочитали полтора миллиона раз.
Типы данных и ограничения SQL
Правильный выбор типов данных — основа производительной и надёжной базы. Базовые типы SQL:
- Числовые:
INTEGER,BIGINT,DECIMAL(10,2),FLOAT - Строковые:
VARCHAR(255),TEXT,CHAR(10) - Дата и время:
DATE,TIMESTAMP,INTERVAL - Логический:
BOOLEAN - JSON:
JSON/JSONB(PostgreSQL) — для полуструктурированных данных
Ограничения (constraints) — это правила, которые СУБД проверяет автоматически при каждой вставке и обновлении:
PRIMARY KEY гарантирует уникальность строки. FOREIGN KEY связывает таблицы и не даёт создать «висячие» ссылки. NOT NULL запрещает пустые значения. CHECK валидирует данные по условию. Вместе эти ограничения защищают целостность данных на уровне структуры — СУБД не позволит вставить строку, нарушающую правила.
Операторы и выражения
За базовыми командами идут операторы, которые делают запросы по-настоящему гибкими. WHERE фильтрует строки, LIKE ищет по шаблону с подстановочными знаками (% — любая подстрока, _ — один символ), IN проверяет вхождение в список, BETWEEN задаёт диапазон.
Отдельного внимания заслуживает CASE WHEN — условная логика прямо внутри запроса:
Подробный разбор LIKE с примерами — в отдельной статье.
NULL: подводные камни
NULL — не значение, а отсутствие значения. NULL = NULL возвращает не TRUE, а NULL. Единственный способ проверки — IS NULL / IS NOT NULL.
Функции даты и времени
Работа с датами — повседневная задача аналитика:
NOW()/CURRENT_DATE— текущий момент / датаDATE_TRUNC('month', ts)— округление до начала периодаEXTRACT(YEAR FROM ts)— извлечение части датыts + INTERVAL '7 days'— арифметика с датами
Строковые и математические функции
Помимо дат и агрегатов, SQL предоставляет богатый набор функций для работы со строками и числами. Строковые функции: CONCAT — склейка строк, SUBSTRING — извлечение подстроки, LENGTH — длина строки, UPPER / LOWER — смена регистра, REPLACE — замена подстроки, TRIM — удаление пробелов по краям. Математические: ROUND — округление, ABS — модуль числа, CEIL / FLOOR — округление вверх и вниз. Эти функции работают одинаково в PostgreSQL, MySQL и других СУБД (с минимальными различиями в именах).
Операторы множеств: UNION, INTERSECT, EXCEPT
Эти операторы объединяют результаты нескольких запросов:
UNION— объединение с удалением дубликатов.UNION ALL— без удаления (быстрее)INTERSECT— пересечение (строки из обоих запросов)EXCEPT— разность (строки из первого, которых нет во втором)
Агрегатные функции SQL
Агрегатные функции вычисляют одно значение по набору строк: COUNT, SUM, AVG, MIN, MAX. Работают в связке с GROUP BY.
Нюансы, которые часто путают:
COUNT(*)считает все строки (включая NULL).COUNT(column)— только строки, где column не NULLCOUNT(DISTINCT column)— количество уникальных значенийAVGигнорирует NULL — если NULL означает «0», результат будет завышен
Подзапросы, CTE и представления
Когда запрос становится сложным, его нужно декомпозировать. Для этого есть три инструмента.
Подзапросы
Запрос внутри запроса. Бывают скалярные (возвращают одно значение), табличные (набор строк) и коррелированные (ссылаются на внешний запрос):
CTE (Common Table Expressions)
Конструкция WITH позволяет дать имя подзапросу и переиспользовать его. CTE делают сложные запросы читаемыми, а рекурсивные CTE позволяют обходить деревья и графы:
Рекурсивные CTE
Рекурсивные CTE обходят деревья и графы — например, оргструктуру компании или вложенные категории:
Представления (Views)
CREATE VIEW создаёт «виртуальную таблицу» — именованный запрос, к которому можно обращаться как к обычной таблице. Это удобно для инкапсуляции сложной логики и разграничения доступа. Материализованные представления (MATERIALIZED VIEW в PostgreSQL) хранят результат физически и обновляются по команде — полезно для тяжёлых аналитических запросов.
Хранимые процедуры и функции
Хранимые процедуры и функции — SQL-код, сохранённый на сервере СУБД. Функция возвращает значение и вызывается в SELECT, процедура выполняет действия и вызывается через CALL.
Когда использовать:
- Инкапсуляция бизнес-логики на уровне базы (расчёт скидок, начисление бонусов)
- Повторяющиеся многошаговые операции (ежемесячные отчёты, архивация)
- Безопасность:
SECURITY DEFINERпозволяет давать доступ к функции, не давая доступ к таблицам
Когда не использовать:
- Логику приложения лучше держать в коде — её проще тестировать и деплоить
- Тяжёлые вычисления: масштабировать сервер СУБД дороже, чем сервер приложения
- Бизнес-логика, которая часто меняется — миграции хранимых процедур болезненнее, чем код
Триггеры — особый тип: они срабатывают автоматически при INSERT/UPDATE/DELETE. Полезны для аудита (логировать все изменения) и автоматических вычислений, но злоупотреблять не стоит — скрытая логика усложняет отладку.
Оконные функции SQL
Оконные функции — это то, что отделяет новичка от уверенного SQL-разработчика. Они выполняют вычисления по «окну» строк, не сворачивая результат как GROUP BY. Вы получаете и агрегат, и исходные строки одновременно.
Ключевые функции: ROW_NUMBER() для нумерации, RANK() / DENSE_RANK() для ранжирования, LAG() / LEAD() для сравнения с соседними строками, агрегатные функции с OVER() для скользящих средних и нарастающих итогов.
Типичные задачи: топ-N в каждой группе, рост метрики месяц к месяцу, скользящее среднее за 7 дней. Без оконных функций эти задачи требуют громоздких подзапросов.
RANK() пропускает позиции после одинаковых значений (1, 2, 2, 4), а DENSE_RANK() — нет (1, 2, 2, 3). Для скользящих агрегатов используется конструкция ROWS BETWEEN — например, ROWS BETWEEN 6 PRECEDING AND CURRENT ROW для скользящего среднего за 7 дней.
Детальный разбор с визуальными примерами — в нашей статье об оконных функциях SQL.
Транзакции и ACID в SQL
Транзакция — группа операций, которые выполняются как единое целое: либо всё, либо ни одна. Классический пример — перевод денег:
Если между двумя UPDATE произойдёт сбой, ROLLBACK откатит обе операции — деньги не потеряются и не удвоятся. Для частичного отката используется SAVEPOINT: можно откатить транзакцию не целиком, а до определённой точки (ROLLBACK TO SAVEPOINT имя).
Свойства ACID гарантируют надёжность транзакций:
- Atomicity (атомарность) — транзакция неделима: либо выполнена полностью, либо отменена целиком
- Consistency (согласованность) — после транзакции база остаётся в корректном состоянии, все ограничения соблюдены
- Isolation (изоляция) — параллельные транзакции не мешают друг другу. Уровни: от READ UNCOMMITTED (быстро, но грязные чтения) до SERIALIZABLE (безопасно, но медленно)
- Durability (долговечность) — после COMMIT данные сохранены даже при аварии сервера
ACID — фундамент надёжности реляционных баз данных. Именно эти свойства гарантируют, что данные не потеряются и не «рассинхронятся» даже при сбоях и параллельных запросах.
Уровни изоляции
Свойство Isolation на практике настраивается через уровни изоляции. Каждый уровень — компромисс между корректностью и производительностью:
- READ UNCOMMITTED — самый слабый: видны незакоммиченные изменения других транзакций (dirty reads). Практически не используется
- READ COMMITTED — видны только закоммиченные данные. По умолчанию в PostgreSQL. Достаточно для большинства приложений
- REPEATABLE READ — повторное чтение строки всегда даёт тот же результат. По умолчанию в MySQL. Защищает от non-repeatable reads
- SERIALIZABLE — максимальная изоляция, транзакции ведут себя как последовательные. Нужен для финансовых операций и бронирований
Нормализация и проектирование схем
Нормализация — процесс организации таблиц так, чтобы минимизировать дублирование данных и аномалии при вставке, обновлении и удалении.
Три ключевые нормальные формы:
- 1NF — каждая ячейка содержит одно атомарное значение. Никаких «Москва, Питер» в одном поле — разносим по строкам или связанным таблицам
- 2NF — все неключевые столбцы зависят от всего первичного ключа, а не от его части. Актуально для составных ключей
- 3NF — неключевые столбцы не зависят друг от друга. Если город определяет страну, нужна отдельная таблица городов
Пример: таблица заказов до и после нормализации до 3NF:
В этом примере мы устранили дублирование данных клиента (2NF). Для полной 3NF нужно было бы вынести и города в отдельную таблицу, если город определяет дополнительные атрибуты (страну, регион).
На практике большинство баз проектируют в 3NF. Но иногда данные намеренно денормализуют — например, в аналитических хранилищах (OLAP), где скорость чтения важнее экономии места. Схемы «звезда» и «снежинка» в data warehouse — это контролируемая денормализация.
Производительность и оптимизация
Когда таблица вырастает до миллионов строк, наивные запросы начинают тормозить. Первый инструмент диагностики — EXPLAIN ANALYZE: он показывает, какой план выбрал оптимизатор, сколько строк просканировал и где узкое место.
Типичные антипаттерны:
SELECT *вместо конкретных столбцов — читает больше данных, чем нужно- Отсутствие индекса на столбцах в WHERE и JOIN — приводит к полному сканированию таблицы (Seq Scan)
- Функции на индексированных столбцах:
WHERE UPPER(email) = ...— индекс не используется - N+1 запросы из ORM — 1 запрос за список + N запросов за детали каждой записи
Индексы — главный способ ускорения. B-tree индекс (по умолчанию) подходит для большинства задач: точные совпадения, диапазоны, сортировка. PostgreSQL также поддерживает GiST (геоданные), GIN (полнотекстовый поиск, JSONB) и BRIN (временные ряды).
Глубокий разбор типов индексов и их применения — в нашей статье об индексах PostgreSQL.
Безопасность: SQL-инъекции
SQL-инъекция — одна из самых опасных уязвимостей веб-приложений, стабильно входящая в OWASP Top 10. Суть: если пользовательский ввод подставляется в запрос без обработки, злоумышленник может изменить логику запроса.
Классический пример — форма логина:
Защита проста и надёжна — параметризованные запросы (prepared statements):
Пароли в реальных приложениях никогда не хранят и не сравнивают в открытом виде — их хешируют (bcrypt, argon2), а проверку выполняет код приложения, не SQL-запрос.
При использовании ORM (SQLAlchemy, Django ORM, Prisma) параметризация происходит автоматически. Если пишете raw SQL — никогда не вставляйте пользовательский ввод через конкатенацию строк или f-строки.
Управление доступом: GRANT и REVOKE
Вторая линия защиты — принцип минимальных привилегий. Приложению не нужен суперпользователь базы данных:
REVOKE отзывает права. В PostgreSQL также доступна Row-Level Security (RLS) — ограничение видимости строк в зависимости от роли: каждый менеджер видит только своих клиентов.
Современный SQL: JSON, диалекты и стандарт SQL:2023
SQL — не замороженный язык из 80-х. Стандарт активно развивается, и последняя версия SQL:2023 (опубликована в июне 2023) принесла два крупных нововведения:
- SQL/JSON — стандартизированные функции для работы с JSON прямо в SQL-запросах. PostgreSQL поддерживает
JSONBс 2014 года, а теперь аналогичные возможности появляются и в других СУБД - SQL/PGQ (Property Graph Queries) — графовые запросы внутри SQL. Можно искать пути и паттерны в связанных данных без отдельной графовой базы
На практике каждая СУБД имеет свой диалект:
- PostgreSQL — PL/pgSQL, JSONB, массивы, расширения (PostGIS, pg_trgm). Ближе всего к стандарту
- MySQL — оконные функции появились поздно — только в версии 8.0 (2018), LIMIT вместо FETCH FIRST
- T-SQL (Microsoft SQL Server) — TOP вместо LIMIT, IDENTITY вместо SERIAL, мощные CTE
- PL/SQL (Oracle) — ROWNUM, CONNECT BY для иерархий, пакеты (packages)
- Cloud SQL — BigQuery, Redshift, Snowflake имеют свои расширения, но базовый SQL везде одинаков
Хорошая новость: базовый синтаксис (SELECT, JOIN, GROUP BY, оконные функции) одинаков во всех диалектах. Освоив стандартный SQL на PostgreSQL, вы легко перейдёте на любую другую СУБД.
PostgreSQL и MySQL
PostgreSQL
PostgreSQL — самая популярная реляционная СУБД для новых проектов. Полная поддержка SQL-стандарта, JSONB для полуструктурированных данных, расширения (PostGIS для геоданных, pg_trgm для нечёткого поиска), продвинутая система типов и отличная производительность.
15 самых полезных команд PostgreSQL — от размера базы до профилирования запросов — в нашей подборке. А для оптимизации больших таблиц — разбор индексов PostgreSQL.
MySQL
MySQL — одна из старейших популярных open-source СУБД, движок WordPress и множества legacy-систем. Проще в настройке, но имеет подводные камни: неявное приведение типов, особенности GROUP BY, различия между InnoDB и MyISAM.
Самые частые ошибки — от кодировок до потери данных — в нашей статье о типичных ошибках MySQL.
Выбор СУБД: SQL vs NoSQL
SQLite — для встраиваемых сценариев: мобильные приложения, Electron, edge computing, прототипы (вся база в одном файле). MySQL — проверенный выбор для веб-приложений, на нём работают GitHub и Booking.com. PostgreSQL — универсальный вариант для новых проектов, от стартапов до enterprise. Детальное сравнение с бенчмарками — в нашем обзоре трёх СУБД.
Когда данные неструктурированные или нужна горизонтальная масштабируемость, рассмотрите NoSQL: MongoDB (документы), Redis (ключ-значение), Cassandra (колонки), Neo4j (графы). Подробнее — в статье о моделях баз данных.
SQL на собеседованиях
SQL-вопросы — обязательная часть собеседований для бэкенд-разработчиков, аналитиков и дата-инженеров. Типичный формат: дают схему из 2–3 таблиц и просят написать запрос. Темы: JOIN-ы, GROUP BY, оконные функции, подзапросы, нормализация.
Ключ к успеху — практика на реальных задачах. Интервьюеры оценивают умение декомпозировать задачу, выбрать правильный тип JOIN и грамотно обработать NULL.
27 самых распространённых вопросов с ответами — в нашей подборке. Для практики — 5 заданий с реальных собеседований с разбором решений.
Частые вопросы
Какой диалект SQL учить первым?
Стандартный SQL — он одинаков на 90% во всех СУБД. Для практики лучше PostgreSQL: ближе к стандарту и наиболее востребован. Специфику MySQL или SQLite освоите за пару дней.
PostgreSQL или MySQL — что выбрать для нового проекта?
PostgreSQL — если важна корректность, расширяемость и работа со сложными типами (JSON, массивы, геоданные). MySQL — если нужна простота и команда уже знает его. Для новых проектов в 2026 чаще выбирают PostgreSQL.
Сколько времени нужно, чтобы выучить SQL?
Базовые запросы (SELECT, WHERE, JOIN, GROUP BY) — 2–3 недели ежедневной практики. Уверенный средний уровень (подзапросы, оконные функции, оптимизация) — 2–3 месяца. Экспертный уровень (планы выполнения, партиционирование, администрирование) — от полугода реального опыта.
Чем отличаются WHERE и HAVING?
WHERE фильтрует строки до группировки, HAVING — после. Поэтому в HAVING можно использовать агрегатные функции (COUNT, SUM, AVG), а в WHERE — нельзя. Пример: WHERE salary > 100000 фильтрует отдельных сотрудников, HAVING AVG(salary) > 100000 фильтрует целые отделы.
Что такое CTE и зачем он нужен?
CTE (Common Table Expression) — именованный подзапрос в конструкции WITH. Делает сложные запросы читаемыми, позволяет переиспользовать промежуточные результаты, а рекурсивные CTE обходят деревья и графы. Доступен во всех современных СУБД.
Как защититься от SQL-инъекций?
Использовать параметризованные запросы (prepared statements) вместо конкатенации строк. Если работаете через ORM — защита встроена. Если пишете raw SQL — никогда не вставляйте пользовательский ввод через f-строки или string formatting.
SQL устареет?
Нет. SQL существует с 1974 года и набирает обороты. Даже NoSQL-базы добавляют SQL-подобный синтаксис (CQL в Cassandra, N1QL в Couchbase). Новые инструменты (dbt, Malloy) строятся поверх SQL. ИИ-помощники генерируют SQL, но проверять и понимать его должен человек.
Куда двигаться дальше
SQL — это фундамент, но не потолок. Направления для роста:
- Администрирование БД — репликация, бэкапы, мониторинг, настройка производительности
- Дата-инженерия — ETL-пайплайны, dbt, Airflow, data warehouse (BigQuery, Snowflake)
- Аналитика данных — SQL + Python (pandas), визуализация, A/B-тесты
- Бэкенд-разработка — ORM (SQLAlchemy, Prisma, GORM), миграции, проектирование схем
- Data Science — feature engineering, работа с большими датасетами
Главный совет: практикуйтесь на реальных данных. Поднимите PostgreSQL локально, загрузите публичный датасет и решайте задачи. Ресурсы для старта:
- SQLBolt — интерактивные уроки SQL в браузере, от нуля
- PostgreSQL Exercises — задачи на реальной схеме (клуб, бронирования)
- LeetCode / HackerRank — SQL-задачи для подготовки к собеседованиям
- Kaggle Datasets — открытые датасеты для импорта в PostgreSQL и экспериментов