Перейти к основному содержимому

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 → проверка SELECTCOMMIT/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практикум 111SQL — реальные кейсы (разбор по строкам) → 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 — о разделе"

Проверьте себя: Чек-лист самопроверки.