SQL — итоги
Кратко — что стоит унести из раздела "SQL". Если пункт кажется туманным — откройте указанную главу или оглавление.
FAQ — Часто задаваемые вопросы
Типичные ошибки и затыки при первых запросах, миграциях и отладке SQL. Здесь — как диагностировать и что перечитать; формулировки для самопроверки — в чек-листе.
Вопрос. SELECT с JOIN вернул в десятки раз больше строк, чем ожидали — "дублируются клиенты".
Ответ. Часто это декартово произведение — забыли условие связи в ON/WHERE или JOIN идёт по неверному ключу. Сверьте первичный и внешний ключ, добавьте COUNT(*) по таблицам по отдельности. Подробнее здесь — JOIN, четыре JOIN на одном примере.
Вопрос. WHERE status = NULL не находит строки со "значением NULL".
Ответ. В SQL сравнение с NULL через = даёт UNKNOWN. Используйте IS NULL / IS NOT NULL или COALESCE для подстановки. Подробнее здесь — Фильтрация и NULL.
Вопрос. COUNT(*) показывает 1000, а COUNT(email) — 950. Куда делись 50 строк?
Ответ. COUNT(столбец) не считает NULL в этом столбце. Для "сколько строк в таблице" — COUNT(*); для "сколько заполненных email" — COUNT(email). Подробнее здесь — Фильтрация и группировка, SELECT.
Вопрос. Запрос с HAVING падает с ошибкой "column must appear in GROUP BY".
Ответ. В SELECT и HAVING после группировки можно использовать только столбцы из GROUP BY или агрегаты. Поля фильтра "до группировки" переносите в WHERE. Подробнее здесь — агрегаты и группировка, SELECT.
Вопрос. Поставили DISTINCT, но строки всё равно "повторяются" — отличается одно поле.
Ответ. DISTINCT сравнивает всю строку результата, а не "логическую сущность". Если в SELECT лишние столбцы — дубликаты останутся. Иногда нужен GROUP BY по ключу сущности или подзапрос. Подробнее здесь — SELECT, практикум shop_data.
Вопрос. LEFT JOIN "пропал" — клиенты без заказов исчезли из результата.
Ответ. Фильтр по столбцу правой таблицы в WHERE превращает LEFT JOIN в INNER. Условие на правую таблицу перенесите в ON, если нужны NULL справа. Подробнее здесь — JOIN.
Вопрос. На тестовой базе запрос мгновенный, на production — минуты при "той же" логике.
Ответ. Объём данных и статистика планировщика меняют план: Seq Scan на миллионах строк — норма без индекса. Снимите EXPLAIN (ANALYZE) на production-like объёме. Подробнее здесь — Оптимизация SQL, принципы SQL-движка.
Вопрос. Создали индекс на (a, b), а запрос фильтрует только по b — индекс "не работает".
Ответ. Составной B-tree индекс эффективен, когда условие использует левый префикс (a) или (a, b). Для фильтра только по b нужен отдельный индекс или перестройка запроса. Подробнее здесь — сложные индексы, оптимизация.
Вопрос. INSERT падает: violates foreign key constraint — строка "точно есть".
Ответ. Родительская строка может быть в другой схеме/БД, удалена в той же транзакции позже или ключ другого типа (строка "5" vs число 5). Проверьте SELECT по точному значению FK и порядок вставок. Подробнее здесь — Реляционная модель, практикум.
Вопрос. UPDATE orders SET status = 'cancelled' без WHERE — "случайно отменили всё".
Ответ. В SQL без WHERE обновляется каждая строка таблицы. На стенде используйте транзакцию с BEGIN → проверка SELECT → COMMIT/ROLLBACK; в GUI — preview. Подробнее здесь — Транзакции, категории команд.
Вопрос. Приложение получило ошибку deadlock — "кто виноват, мы или база"?
Ответ. Deadlock — циклическое ожидание блокировок двух транзакций; СУБД убивает одну. Исправление — единый порядок обновления таблиц, короткие транзакции, retry в коде. Подробнее здесь — Блокировки PostgreSQL, конкурентный доступ.
Вопрос. ALTER TABLE ADD COLUMN на большой таблице "завис" и блокирует сайт.
Ответ. В зависимости от СУБД и версии DDL может брать эксклюзивную блокировку. Планируйте окно обслуживания, online DDL (MySQL/InnoDB, PostgreSQL CONCURRENTLY для индексов) или миграцию через новую таблицу. Подробнее здесь — PostgreSQL API, управление РСУБД.
Вопрос. Сортировка дат в текстовом столбце VARCHAR даёт "2024-10-01" перед "2024-2-01".
Ответ. Строки сортируются лексически, а не как даты. Храните даты в типах DATE/TIMESTAMP или приводите в ORDER BY через ::date / STR_TO_DATE. Подробнее здесь — типы данных, SELECT.
Вопрос. WHERE a = 1 OR a = 2 OR a = 3 … — индекс есть, план всё равно Seq Scan.
Ответ. Длинные цепочки OR по разным значениям часто ломают использование одного индекса — попробуйте IN (...) или перепишите через UNION ALL. Подробнее здесь — оптимизация, Фильтрация.
Вопрос. Подзапрос в WHERE тормозит — JOIN тот же результат за секунду.
Ответ. Планировщик иногда материализует подзапрос построчно (correlated). Перепишите в JOIN или EXISTS с индексом на связь; сверьте планы через EXPLAIN. Подробнее здесь — Подзапросы и EXISTS, JOIN.
Вопрос. UNION убрал дубликаты и стал медленным — можно быстрее?
Ответ. UNION делает дедупликацию (sort/hash); если дубликаты допустимы — UNION ALL без лишней работы. Подробнее здесь — SELECT, шпаргалка задач.
Вопрос. EXPLAIN показывает Index Scan, а время запроса всё равно большое.
Ответ. Индекс мог вернуть много строк (низкая селективность) или основное время уходит на sort/hash/join. Смотрите EXPLAIN ANALYZE, rows, buffers и фильтруйте раньше. Подробнее здесь — Оптимизация SQL.
Вопрос. Установил PostgreSQL, psql пишет "connection refused" или "role does not exist".
Ответ. Проверьте, запущена ли служба, верный ли порт/хост, существует ли роль и правила в pg_hba.conf. На Windows часто мешает неверный пользователь OS vs PostgreSQL. Подробнее здесь — Первые шаги с SQL, PostgreSQL.
Вопрос. Запрос из туториала MySQL падает в PostgreSQL — "syntax error near LIMIT".
Ответ. Диалекты SQL различаются: кавычки идентификаторов, функции дат, LIMIT/TOP/FETCH, булевы типы, IFNULL vs COALESCE. Сверьтесь со шпаргалкой четырёх СУБД. Подробнее здесь — MySQL, PostgreSQL.
Вопрос. Склеили SQL строкой: "SELECT * FROM users WHERE id = " + userId — безопасно для внутреннего API?
Ответ. Часто это декартово произведение — забыли условие связи в ON/WHERE или JOIN идёт по неверному ключу. Сверьте первичный и внешний ключ, добавьте COUNT(*) по таблицам по отдельности. Подробнее здесь — JOIN, четыре JOIN на одном примере.
Вопрос. ORM генерирует сотни мелких SELECT вместо одного JOIN — страница "умирает".
Ответ. Это N+1: для каждой строки отдельный запрос связей. Решение — eager loading, JOIN в одном запросе или batch fetch. Подробнее здесь — JOIN, оптимизация.
Вопрос. Оконная функция и GROUP BY в одном запросе — ошибка или "странный результат".
Ответ. Оконные функции считаются по партиции без схлопывания строк; агрегаты с GROUP BY уменьшают число строк. Смешивайте осознанно: сначала CTE с группировкой, затем OVER(). Подробнее здесь — Оконные функции, CTE.
Вопрос. Рекурсивный CTE для оргструктуры крутится бесконечно.
Ответ. В данных есть цикл (сотрудник начальник сам себе) или нет условия остановки в рекурсивной части. Проверьте FK, добавьте лимит глубины или фильтр посещённых id. Подробнее здесь — CTE, иерархии.
Вопрос. LIMIT 10 OFFSET 100000 на каталоге товаров — каждая страница всё медленнее.
Ответ. OFFSET заставляет СУБД пропустить N строк, всё равно их прочитав. Для глубокой пагинации — ключ (created_at, id) > last_seen. Подробнее здесь — SELECT, оптимизация.
Вопрос. Нормализовали схему "по учебнику", отчёт с десятью JOIN стал неприемлемым.
Ответ. Нормализация снижает аномалии; для тяжёлых read-путей допустима контролируемая денормализация, материализованные представления или отдельная витрина. Подробнее здесь — Нормализация, оптимизация.
Вопрос. VIEW показывает старые цифры, хотя базовые таблицы уже обновили.
Ответ. Обычный VIEW — это сохранённый запрос; он всегда актуален относительно таблиц. Если цифры "старые" — смотрите кэш приложения, materialized view без REFRESH или реплику read-only с lag. Подробнее здесь — SELECT и представления, транзакции.
Вопрос. BEGIN; … забыли COMMIT — другие пользователи "не видят" новые строки.
Ответ. Открытая транзакция держит блокировки и снимок (в MVCC). Закройте COMMIT/ROLLBACK или переподключитесь; в psql смотрите idle in transaction в pg_stat_activity. Подробнее здесь — Транзакции, блокировки.
Вопрос. Сравнение 'Admin' = 'admin' в PostgreSQL даёт false — "одинаковые" логины не находятся.
Ответ. Сравнение строк чувствительно к регистру (зависит от collation). Для поиска без учёта регистра — ILIKE или LOWER(column) = LOWER(?) с индексом на expression. Подробнее здесь — Фильтрация, функции.
Вопрос. Храним деньги в FLOAT — сумма заказов "не сходится" на копейки.
Ответ. Для денег используйте NUMERIC/DECIMAL, а не float с двоичной погрешностью. Подробнее здесь — Реляционная модель, типы в PostgreSQL.
Вопрос. С чего начать практику, если теорию прочитал, а руки "не помнят синтаксис"?
Ответ. Маршрут: установка → Первые шаги с SQL → тренажёр shop_data → практикум 111 → SQL — реальные кейсы (разбор по строкам) → 885 рецепты. Повторяйте JOIN и GROUP BY на одной схеме, а не на разрозненных примерах.
Вопрос. Что такое SQL простыми словами?
Ответ. SQL (Structured Query Language) — язык запросов к реляционным базам: читать, добавлять, менять и удалять строки в таблицах, описывать схему и права. Подробнее здесь — принципы SQL-движка, реляционная модель.
Вопрос. Как научиться SQL с нуля — пошаговый маршрут?
Ответ. Установите PostgreSQL → 101 первые шаги → SELECT и WHERE → JOIN → GROUP BY → тренажёр. Полный маршрут — оглавление раздела.
Вопрос. Чем SQL отличается от MySQL и PostgreSQL?
Ответ. SQL — язык; MySQL и PostgreSQL — СУБД, которые его реализуют с разным синтаксисом и возможностями. Подробнее здесь — категории команд, шпаргалка четырёх СУБД.
Вопрос. PostgreSQL или MySQL — что выбрать в 2025–2026 году?
Ответ. PostgreSQL — богаче типами, JSON, расширениями; MySQL — распространён в LAMP и хостингах. Для учёбы и новых проектов в энциклопедии рекомендуется PostgreSQL. Подробнее здесь — PostgreSQL, MySQL, выбор СУБД.
Вопрос. SQLite или PostgreSQL — когда хватит встроенной базы?
Ответ. SQLite — файл на диске, один писатель, идеален для мобильных app и прототипов. PostgreSQL — сервер, конкурентность, репликация, production. Подробнее здесь — SQLite, PostgreSQL.
Вопрос. Как написать JOIN в SQL — с чего начать новичку?
Ответ. Свяжите таблицы по ключу: FROM orders o INNER JOIN customers c ON o.customer_id = c.id. Четыре типа JOIN на одном примере — глава 55.
Вопрос. INNER JOIN и LEFT JOIN — в чём разница?
Ответ. INNER JOIN — только совпавшие строки с обеих сторон. LEFT JOIN — все строки слева плюс совпадения справа (NULL, если справа нет). Подробнее здесь — JOIN.
Вопрос. WHERE и HAVING — когда что использовать?
Ответ. WHERE фильтрует строки до группировки; HAVING — группы после GROUP BY (например, HAVING COUNT(*) > 5). Подробнее здесь — группировка, SELECT.
Вопрос. Как удалить дубликаты строк в SQL?
Ответ. SELECT DISTINCT … или GROUP BY по ключу уникальности; для физического удаления — CTE с ROW_NUMBER() и DELETE. Подробнее здесь — SELECT, оконные функции.
Вопрос. Что такое первичный ключ и внешний ключ в базе данных?
Ответ. PK однозначно идентифицирует строку; FK ссылается на PK другой таблицы и обеспечивает ссылочную целостность. Подробнее здесь — реляционная модель, CREATE TABLE.
Вопрос. Нормализация базы данных — зачем нужна 1NF, 2NF, 3NF?
Ответ. Нормализация убирает дублирование и аномалии при UPDATE/INSERT/DELETE: каждый факт — в одном месте, связи через ключи. Подробнее здесь — Нормализация.
Вопрос. ACID транзакции — что это значит простыми словами?
Ответ. Atomicity, Consistency, Isolation, Durability — операции либо целиком применяются, либо откатываются; данные остаются согласованными и переживают сбой после COMMIT. Подробнее здесь — Транзакции, конкурентный доступ.
Вопрос. SQL-инъекция — что это и как защититься?
Ответ. Часто это декартово произведение — забыли условие связи в ON/WHERE или JOIN идёт по неверному ключу. Сверьте первичный и внешний ключ, добавьте COUNT(*) по таблицам по отдельности. Подробнее здесь — JOIN, четыре JOIN на одном примере.
Вопрос. Как установить PostgreSQL на Windows или Linux?
Ответ. Скачайте с postgresql.org или пакетный менеджер → initdb/служба → psql → создайте БД и пользователя. Пошагово — Первые шаги с SQL, администрирование.
Вопрос. EXPLAIN в PostgreSQL — как понять план запроса?
Ответ. EXPLAIN (ANALYZE, BUFFERS) показывает Seq Scan vs Index Scan, стоимость, фактические строки. Ищите узкие места — полный скан больших таблиц, nested loop на миллионах строк. Подробнее здесь — Оптимизация SQL.
Вопрос. Оконные функции SQL — ROW_NUMBER, RANK — для чего нужны?
Ответ. Считают по "окну" строк без схлопывания: топ-N в группе, скользящие суммы, LAG/LEAD для сравнения с предыдущей строкой. Подробнее здесь — Оконные функции.
Вопрос. CTE (WITH) в SQL — что это и когда использовать?
Ответ. Common Table Expression — именованный подзапрос в начале запроса; упрощает чтение и рекурсию (оргструктура). Подробнее здесь — CTE, иерархии.
Вопрос. PostgreSQL — что даёт WITH … AS MATERIALIZED?
Ответ. С PostgreSQL 12 планировщик может встроить CTE в основной запрос: блок WITH исчезает из плана, подзапрос иногда выполняется повторно. Ключевое слово MATERIALIZED фиксирует результат CTE — подзапрос выполняется один раз, дальше читается узел CTE Scan. Для лёгких CTE есть подсказка NOT MATERIALIZED. На больших данных разница по времени иногда достигает десятков раз. Подробнее — CTE и материализация, EXPLAIN в практикуме PostgreSQL.
Вопрос. VIEW и материализованное представление — в чём разница?
Ответ. Обычный VIEW выполняет запрос при каждом обращении. MATERIALIZED VIEW хранит снимок — быстрее читать, нужен REFRESH. Подробнее здесь — SELECT, оптимизация.
Вопрос. Как сделать бэкап PostgreSQL — pg_dump команда?
Ответ. pg_dump -Fc -f backup.dump mydb — логический дамп; восстановление — pg_restore. Для PITR нужен ещё архив WAL. Подробнее здесь — резервное копирование, справочник DBA.
Вопрос. SQL для аналитика данных — какие темы учить в первую очередь?
Ответ. SELECT, JOIN, GROUP BY, агрегаты, оконные функции, подзапросы, работа с датами — затем связка с Pandas/BI. Подробнее здесь — анализ данных, практикум shop_data, SQL — реальные кейсы.
Вопрос. CRUD операции в SQL — какие команды?
Ответ. Create — INSERT; Read — SELECT; Update — UPDATE; Delete — DELETE. Структуру таблиц задаёт DDL (CREATE TABLE). Подробнее здесь — категории команд, SELECT.
Вопрос. Microsoft SQL Server и T-SQL — чем отличаются от PostgreSQL?
Ответ. T-SQL — диалект Microsoft: TOP, IDENTITY, linked servers, SSMS. Синтаксис и администрирование отличаются от PostgreSQL. Подробнее здесь — T-SQL, SQL Server API, 212 DBA.
Вопрос. Индекс в SQL — когда создавать и когда вредит?
Ответ. Индекс ускоряет SELECT/WHERE/JOIN по столбцу, но замедляет INSERT/UPDATE и занимает место. Создавайте под реальные медленные запросы, не "на всё". Подробнее здесь — оптимизация, сложные индексы.
Вопрос. Есть ли бесплатный SQL-тренажёр онлайн для практики?
Ответ. В разделе — встроенный тренажёр shop_data с JOIN и GROUP BY; галерея с построчным разбором — SQL — реальные кейсы; также SQL Generator Online автора проекта. Подробнее здесь — оглавление.
Что запомнить
SQL — это фундаментальная технология управления структурированными данными, возникшая в 1970‑х годах и сохраняющая актуальность на протяжении полувека. В основе SQL лежит реляционная модель данных, предложенная Эдгаром Коддом: данные организованы в таблицы, строки и столбцы с чётко определёнными типами и ограничениями. Эта модель обеспечивает предсказуемость, целостность и декларативность — ключевые качества для систем, где важны точность и надёжность.
Современный SQL — это стандартизированный (ANSI/ISO), но гибкий язык — от базового DML (INSERT, SELECT, UPDATE, DELETE — в приложениях это CRUD) до оконных функций, рекурсивных CTE и подзапросов. Структуру задаёт DDL (CREATE TABLE и др.) — другой класс команд, не "буква C" из CRUD. Дополнительно — DCL, транзакции (ACID), хранимые процедуры и триггеры.
Несмотря на появление NoSQL и других парадигм, SQL остаётся доминирующей моделью в корпоративных, финансовых, государственных и регулируемых системах. Причины просты — строгая схема предотвращает ошибки на ранних этапах, внешние ключи и ограничения гарантируют согласованность, а мощный оптимизатор запросов позволяет эффективно обрабатывать миллионы строк без написания императивного кода. Даже в системах, использующих NoSQL для операционных данных, SQL часто применяется на этапе аналитики — через OLAP-хранилища, материализованные представления или ETL-процессы.
Важно понимать: знание SQL — это освоение мышления в терминах множеств и отношений. Успешный запрос строится не путём проб и ошибок, а через чёткое понимание — какие таблицы участвуют, как они связаны, какие фильтры применяются, как группируются результаты и какие агрегаты нужны. Эффективность достигается не только правильностью, но и производительностью — через грамотное использование индексов, избегание N+1-проблем, минимизацию сканирования и оптимизацию плана выполнения.
SQL — это язык, который учит дисциплине — каждое поле имеет тип, каждая связь — смысл, каждая операция — последствия. В эпоху ИИ и больших данных эта дисциплина становится особенно ценной. Именно поэтому SQL остаётся обязательным навыком не только для разработчиков и аналитиков, но и для архитекторов, тестировщиков и инженеров данных.
Куда идти дальше
| Тема | Раздел |
|---|---|
| "Контейнеризация и оркестрация — о разделе" | "Контейнеризация и оркестрация — о разделе" |
| "JavaScript — о разделе" | "JavaScript — о разделе" |
| "Микросервисы и интеграция — о разделе" | "Микросервисы и интеграция — о разделе" |
| "Python — о разделе" | "Python — о разделе" |
Проверьте себя: Чек-лист самопроверки.