SQL-запросы это не страшно! Вся база с примерами

SQL спрашивают на каждом втором собеседовании аналитика, тестировщика или разработчика

SQL-запросы это не страшно! Вся база с примерами

Если вы хотите работать аналитиком, тестировщиком или разработчиком, SQL — это то, о чём вас обязательно спросят на собеседовании. По данным hh.ru, более 80% вакансий аналитиков данных в России требуют хотя бы базового знания SQL. Хорошая новость: язык устроен логично, читается почти как английская фраза, а базу можно освоить за один вечер.

В этой статье разберём все основные группы команд, уделим особое внимание SELECT во всей его красе, объясним JOIN без страха и разберём типичные ошибки новичков.

К этой таблице прилагается файл SQL, в котором собраны все примеры из таблицы. Копируйте первый запросы и попробуйте создать ими таблицы. Выполняйте остальные запросы из статьи по мере чтения, если хотите. Не стесняйтесь пробовать и экспериментировать! Примеры работают с PostgreSQL 14+.

Что такое SQL

SQL (Structured Query Language) — это язык запросов для работы с реляционными базами данных. С его помощью вы «разговариваете» с базой: просите найти данные, добавить запись, изменить или удалить её.

Реляционная база данных — это набор связанных таблиц. Представьте Excel: каждый лист — таблица, строки — записи, столбцы — поля. SQL позволяет работать с этими таблицами через текстовые команды.

История языка началась в 1974 году в лабораториях IBM — именно там Дональд Чемберлин и Рэймонд Бойс разработали прообраз SQL для системы управления данными. С тех пор язык стандартизирован (ISO/IEC 9075) и поддерживается всеми популярными СУБД: PostgreSQL, MySQL, SQLite, MS SQL Server, Oracle.

SQL применяется везде, где есть структурированные данные: интернет-магазины хранят в нём каталоги и заказы, банки — транзакции, приложения — пользовательские профили. В реальных API данные часто приходят в формате JSON, а затем сохраняются или обрабатываются через SQL-запросы.

С какой СУБД начать? Для обучения лучше всего подходит PostgreSQL: бесплатный, мощный, широко используется в продакшене. SQLite — ещё проще в установке и идеален для экспериментов.

Виды SQL-запросов

SQL-команды делятся на четыре группы в зависимости от того, что они делают:

ГруппаРасшифровкаНазначениеОсновные команды
DDLData Definition LanguageСоздание и изменение структуры базыCREATE, ALTER, DROP, TRUNCATE
DMLData Manipulation LanguageРабота с данными внутри таблицSELECT, INSERT, UPDATE, DELETE
DCLData Control LanguageУправление правами доступаGRANT, REVOKE
TCLTransaction Control LanguageУправление транзакциямиBEGIN, COMMIT, ROLLBACK

Большинство повседневных задач решается командами DML. DDL нужен при проектировании базы. DCL и TCL — при работе с многопользовательскими системами.

DDL — команды структуры

DDL-команды определяют, как устроена ваша база: какие таблицы существуют, какие в них столбцы и какого типа данные они хранят. Эти команды меняют саму структуру, а не содержимое.

CREATE TABLE

Самая важная DDL-команда — создаёт новую таблицу.

CREATE TABLE employees (
    id          INT           PRIMARY KEY,
    name        VARCHAR(100)  NOT NULL,
    department  VARCHAR(50),
    salary      DECIMAL(10,2),
    hired_at    DATE,
    is_active   BOOLEAN       DEFAULT TRUE
);

Разберём, что здесь происходит. После CREATE TABLE указывается имя таблицы. Внутри скобок — список столбцов: имя, тип данных и необязательные ограничения.

Основные типы данных SQL, которые встретятся чаще всего:

  • INT — целое число (возраст, количество, идентификатор)
  • VARCHAR(n) — строка до n символов (имя, адрес, email)
  • TEXT — длинный текст без ограничений
  • DECIMAL(p,s) — дробное число с точностью (цены, координаты)
  • DATE — дата в формате YYYY-MM-DD
  • BOOLEAN — истина или ложь

PRIMARY KEY означает, что столбец — уникальный идентификатор каждой строки. NOT NULL запрещает пустые значения. DEFAULT задаёт значение по умолчанию.

ALTER TABLE и DROP

ALTER TABLE позволяет изменить уже существующую таблицу без потери данных.

–– Добавить новый столбец

ALTER TABLE employees ADD COLUMN phone VARCHAR(20);

–– Удалить столбец

ALTER TABLE employees DROP COLUMN phone;

–– Переименовать столбец

ALTER TABLE employees RENAME COLUMN name TO full_name;

DROP TABLE удаляет таблицу целиком — вместе со всеми данными, навсегда.

DROP TABLE employees;

DROP TABLE необратима. Прежде чем выполнять её в рабочей базе, убедитесь, что у вас есть резервная копия.

TRUNCATE TABLE оставляет структуру таблицы нетронутой, но удаляет все строки — быстрее, чем DELETE без WHERE:

TRUNCATE TABLE employees;

DML — работа с данными

DML — это сердце SQL. Именно эти команды используются каждый день: выбрать данные, добавить запись, обновить значение, удалить строку.

  • SELECT — читает данные (самая частая операция)
  • INSERT — добавляет новые строки
  • UPDATE — изменяет существующие строки
  • DELETE — удаляет строки

Разберём каждую команду подробно, начав с SELECT — он заслуживает отдельного раздела.

Успейте: скидка 15% до 29 мая

Если хотите не просто писать SQL-запросы, но и понимать, как базы данных устроены изнутри, — держите промокод Практикума на любой платный курс: по ссылке (можно просто нажать). Даёт скидку 15% при покупке, плюс дополнительно 5 мини-курсов и 5 книг стоимостью ~75 000 ₽. Но только до 29 мая — потом всё, промокод сгорит.

SELECT — главный запрос

SELECT позволяет получить данные из таблицы. Полный синтаксис выглядит так:

SELECT  столбцы
FROM    таблица
WHERE   условие_фильтрации_строк
GROUP BY столбец_группировки
HAVING  условие_фильтрации_групп
ORDER BY столбец_сортировки
LIMIT   количество_строк;

Обязательны только SELECT и FROM. Остальные части добавляются по мере необходимости.

Простейший запрос — получить всё содержимое таблицы:

SELECT * FROM employees;

Звёздочка означает «все столбцы». Лучше перечислить нужные явно:

SELECT name, salary, department FROM employees;

Это быстрее, нагляднее и не сломается, если в таблицу добавят новый столбец.

Можно задать псевдоним через AS:

SELECT name AS employee_name, salary AS monthly_pay
FROM employees;

WHERE и операторы

WHERE фильтрует строки по условию. В результат попадают только те строки, для которых условие истинно.

–– Только сотрудники отдела разработки

SELECT * FROM employees WHERE department = ‘Development’;

–– Зарплата больше 80 000

SELECT name, salary FROM employees WHERE salary > 80000;

–– Зарплата от 50 000 до 100 000

SELECT name, salary FROM employees WHERE salary BETWEEN 50000 AND 100000;

–– Несколько конкретных отделов

SELECT * FROM employees WHERE department IN (‘Development’, ‘Design’, ‘Analytics’);

–– Имя начинается на «Ал»

SELECT * FROM employees WHERE name LIKE ‘Ал%’;

–– Сотрудники без указанного телефона

SELECT * FROM employees WHERE phone IS NULL;

Операторы сравнения: =, != (или <>), >, <, >=, <=.

Условия комбинируются через логические операторы:

–– И то и другое

SELECT * FROM employees WHERE department = ‘Development’ AND salary > 90000;

–– Одно из двух

SELECT * FROM employees WHERE department = ‘Design’ OR department = ‘Analytics’;

–– Не активные сотрудники

SELECT * FROM employees WHERE NOT is_active;

Важное про NULL: сравнение phone = NULL не работает! Для проверки на пустоту всегда используйте IS NULL или IS NOT NULL.

LIKE поддерживает два подстановочных знака: % — любое количество любых символов, _ — ровно один любой символ. Например, LIKE ‘_ван%’ найдёт «Иван», «Дван», «Эвандро».

GROUP BY и агрегатные функции

GROUP BY группирует строки с одинаковым значением в указанном столбце. Вместе с ним используются агрегатные функции, которые вычисляют итог по каждой группе:

ФункцияЧто считает
COUNT(*)Количество строк в группе
SUM(столбец)Сумма значений
AVG(столбец)Среднее значение
MIN(столбец)Минимальное значение
MAX(столбец)Максимальное значение

–– Сколько сотрудников в каждом отделе

SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;

–– Средняя и максимальная зарплата по отделам

SELECT
    department,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary
FROM employees
GROUP BY department;

WHERE против HAVING

WHERE фильтрует строки до группировки. HAVING фильтрует группы — то есть работает после GROUP BY и может обращаться к агрегатным функциям.

–– Это не работает

SELECT department, COUNT(*) AS cnt
FROM employees
WHERE COUNT(*) > 5      -- ошибка: агрегатную функцию здесь нельзя использовать
GROUP BY department;

–– Работает! HAVING для фильтрации групп

SELECT department, COUNT(*) AS cnt
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;    -- отделы, где больше 5 сотрудников

Правило простое: если фильтр не использует агрегатную функцию — пишите WHERE; если использует — пишите HAVING.

ORDER BY и LIMIT

ORDER BY сортирует результат по одному или нескольким столбцам.

–– По зарплате от большей к меньшей

SELECT name, salary FROM employees ORDER BY salary DESC;

–– По отделу по алфавиту, внутри отдела — по зарплате

SELECT name, department, salary
FROM employees
ORDER BY department ASC, salary DESC;

ASC — по возрастанию (по умолчанию), DESC — по убыванию.

LIMIT ограничивает количество строк в результате. OFFSET пропускает первые N строк — удобно для пагинации:

–– Топ-10 по зарплате

SELECT name, salary FROM employees ORDER BY salary DESC LIMIT 10;

–– Страница 3 при размере страницы 10 (строки 21–30)

SELECT name, salary FROM employees ORDER BY id LIMIT 10 OFFSET 20;

INSERT, UPDATE, DELETE

INSERT добавляет новые строки в таблицу:

–– Одна строка

INSERT INTO employees (name, department, salary, hired_at)
VALUES ('Алексей Иванов', 'Development', 95000, '2024-03-01');

–– Несколько строк сразу

INSERT INTO employees (name, department, salary, hired_at)
VALUES
    ('Мария Петрова', 'Design', 80000, '2024-03-15'),
    ('Дмитрий Козлов', 'Analytics', 70000, '2024-04-01');

UPDATE изменяет значения в существующих строках:

–– Поднять зарплату конкретному сотруднику

UPDATE employees SET salary = 100000 WHERE id = 42;

–– Обновить несколько столбцов сразу

UPDATE employees
SET salary = salary * 1.1, department = 'Senior Development'
WHERE department = 'Development' AND salary > 90000;

DELETE удаляет строки:

–– Удалить конкретного сотрудника

DELETE FROM employees WHERE id = 42;

–– Удалить всех неактивных

DELETE FROM employees WHERE is_active = FALSE;

Всегда проверяйте UPDATE и DELETE перед выполнением, запустив сначала SELECT с тем же WHERE. UPDATE employees SET salary = 0 без WHERE обнулит зарплату всем сотрудникам. DELETE FROM employees без WHERE удалит все данные. Эти ошибки необратимы.

JOIN — объединение таблиц

Реальные базы данных состоят из множества связанных таблиц. JOIN позволяет объединить их в одном запросе. Этот оператор наводит ужас на многих, но на самом деле не так сложен, как кажется. Проще всего воспринять JOIN через диаграммы Венна. Прежде чем перейти к примеру посмотрите на диаграммы и постарайтесь держать их в голове при разборе примеров ниже.

JOIN — объединение таблиц

Теперь представим две таблицы: employees (сотрудники) и departments (отделы).

-- employees                   	-- departments
-- id | name     | dept_id     	-- id | name        | budget
-- 1  | Иван     | 2            -- 1  | Design      | 500000
-- 2  | Мария    | 1            -- 2  | Development | 900000
-- 3  | Алексей  | NULL        	-- 3  | Analytics   | 300000

INNER JOIN — только строки, у которых есть соответствие в обеих таблицах:

SELECT e.name, d.name AS department, d.budget
FROM employees e
INNER JOIN departments d ON e.dept_id = d.id;
-- Алексей (dept_id = NULL) в результат не попадёт

LEFT JOIN — все строки из левой таблицы, плюс совпадения из правой. Если соответствия нет — поля из правой таблицы будут NULL:

SELECT e.name, d.name AS department
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.id;
-- Алексей попадёт в результат, department будет NULL

RIGHT JOIN — зеркало LEFT JOIN: все строки из правой таблицы, плюс совпадения из левой. На практике используется реже — обычно проще поменять таблицы местами и написать LEFT JOIN.

FULL JOIN (или FULL OUTER JOIN) — все строки из обеих таблиц. Там, где нет соответствия, будет NULL:

SELECT e.name, d.name AS department
FROM employees e
FULL JOIN departments d ON e.dept_id = d.id;

Обратите внимание на псевдонимы таблиц (e и d): они сокращают запись и делают код читаемым. Когда в нескольких таблицах есть столбцы с одинаковым именем (например, id), обязательно указывайте, из какой таблицы берётся столбец: e.id, d.id.

Подзапросы

Подзапрос — это SELECT внутри другого SQL-запроса. Он заключается в скобки и может использоваться в нескольких местах.

Подзапрос в WHERE — отфильтровать строки по результату другого запроса:

–– Сотрудники с зарплатой выше средней

SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

Подзапрос в FROM — использовать результат запроса как временную таблицу:

SELECT dept_name, avg_sal
FROM (
    SELECT department AS dept_name, AVG(salary) AS avg_sal
    FROM employees
    GROUP BY department
) AS dept_stats
WHERE avg_sal > 70000;

Подзапрос в SELECT — добавить вычисляемый столбец:

SELECT name, salary,
    (SELECT AVG(salary) FROM employees) AS company_avg
FROM employees;

DCL и TCL

DCL — управление правами доступа

В многопользовательских системах важно контролировать, кто что может делать.

–– Дать пользователю право читать таблицу

GRANT SELECT ON employees TO analyst_user;

–– Дать право читать и изменять

GRANT SELECT, UPDATE ON employees TO hr_manager;

–– Отозвать права

REVOKE UPDATE ON employees FROM analyst_user;

TCL — управление транзакциями

Транзакция — это набор операций, которые должны выполниться либо все вместе, либо ни одна. Классический пример: перевод денег со счёта на счёт. Нельзя, чтобы деньги списались с одного счёта, но не зачислились на другой.

BEGIN;                          -- начать транзакцию

UPDATE accounts SET balance = balance - 5000 WHERE id = 1;
UPDATE accounts SET balance = balance + 5000 WHERE id = 2;

COMMIT;                         -- зафиксировать оба изменения

-- Или, если что-то пошло не так:
ROLLBACK;                       -- откатить все изменения транзакции

Порядок выполнения SELECT

Здесь — главный источник путаницы у новичков. SQL-запрос пишется в одном порядке, а выполняется в другом.

Порядок выполнения SELECT

Диаграмма выше показывает логический порядок выполнения. Разберём, почему это важно практически.

Когда вы пишете SELECT name AS employee_name … WHERE name LIKE ‘А%’, псевдоним employee_name не работает в WHERE — потому что WHERE выполняется раньше SELECT, и база ещё не знает о вашем псевдониме.

По той же причине нельзя написать HAVING employee_count > 5, если псевдоним задан в SELECT. Нужно повторить агрегатную функцию: HAVING COUNT(*) > 5.

Порядок выполнения объясняет и разницу WHERE / HAVING: WHERE работает на шаге 2 (над сырыми строками), HAVING — на шаге 4 (над уже сгруппированными данными).

Типичные ошибки

1. SELECT * в production-коде

–– Плохо: тянет все столбцы, в том числе ненужные

SELECT * FROM orders;

–– Хорошо: явно указываем нужное

SELECT id, customer_id, total_amount, created_at FROM orders;

2. UPDATE и DELETE без WHERE

–– КАТАСТРОФА: обнуляет зарплату всем

UPDATE employees SET salary = 0;

–– Правильно: всегда с условием

UPDATE employees SET salary = 0 WHERE id = 99;

3. Сравнение с NULL через =

–– Неправильно: никогда не вернёт строки

SELECT * FROM employees WHERE phone = NULL;

–– Правильно

SELECT * FROM employees WHERE phone IS NULL;

4. HAVING вместо WHERE

–– Медленно: сначала группирует всё, потом фильтрует

SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING department = 'Development';

–– Быстрее: фильтрует до группировки

SELECT department, COUNT(*)
FROM employees
WHERE department = 'Development'
GROUP BY department;

5. Забытые псевдонимы при JOIN

–– Ошибка: база не знает, из какой таблицы брать id

SELECT id, name FROM employees JOIN departments ON dept_id = departments.id;

–– Правильно

SELECT e.id, e.name FROM employees e JOIN departments d ON e.dept_id = d.id;

Вы не спрашивали, но мы ответим

Чем SQL отличается от NoSQL?

SQL — язык для работы с реляционными базами (таблицы, строки, связи). NoSQL — собирательное название для нереляционных баз: документных (MongoDB), ключ-значение (Redis), графовых (Neo4j). SQL гарантирует строгую структуру и транзакционность; NoSQL обычно гибче по структуре и лучше масштабируется горизонтально. Для большинства корпоративных приложений SQL — первый выбор.

Можно ли писать SQL без знания программирования?

Да. SQL — декларативный язык: вы описываете что хотите получить, а не как это сделать. Базовые запросы SELECT, INSERT, UPDATE, DELETE не требуют знания циклов, функций или переменных. Аналитики и менеджеры часто работают с SQL без навыков разработки.

В чём разница между WHERE и HAVING?

WHERE фильтрует отдельные строки — работает до группировки и не может использовать агрегатные функции (COUNT, SUM, AVG и т.д.). HAVING фильтрует группы — работает после GROUP BY и специально предназначен для условий с агрегатными функциями. Если условие не содержит агрегатную функцию — всегда пишите WHERE, это быстрее.

Что такое NULL и почему с ним нужно быть осторожным?

NULL — это не ноль и не пустая строка. Это отсутствие значения. Любое арифметическое действие с NULL даёт NULL: 5 + NULL = NULL. Любое сравнение с NULL даёт UNKNOWN (не TRUE и не FALSE): NULL = NULL — ложь. Для проверки на пустоту всегда используйте IS NULL / IS NOT NULL. Также помните, что COUNT(*) считает все строки, а COUNT(column) — только строки, где столбец не NULL.

Какую СУБД выбрать для изучения SQL?

PostgreSQL — лучший выбор для серьёзного изучения: бесплатный, соответствует стандарту SQL, широко используется в продакшене. Установить можно через официальный сайт или облачный сервис ElephantSQL без установки. MySQL — популярен в веб-разработке, чуть мягче в некоторых правилах стандарта. SQLite — нет сервера, файл базы можно открыть прямо на компьютере, идеален для первых экспериментов.

Заключение

Вы разобрали все основные группы SQL-команд: DDL для создания структуры, DML для работы с данными, DCL для управления правами и TCL для транзакций. Отдельно рассмотрели SELECT со всеми его секциями, четыре типа JOIN и подзапросы.

Следующий шаг — научиться делать запросы быстрее. Для этого изучите индексы: они ускоряют поиск по таблице так же, как оглавление ускоряет поиск в книге. Затем разберитесь с EXPLAIN ANALYZE — командой, которая показывает, как именно база выполняет ваш запрос и где теряется время.

Практикуйтесь на реальных данных: сервисы sqltutorial.org и leetcode.com (раздел Database) дают задачи с готовыми таблицами прямо в браузере — без установки чего-либо. А в современных AI-инструментах SQL тоже никуда не исчез: AI-агент может переводить запрос пользователя в SQL, идти в базу данных и возвращать готовую аналитику. Можете поэкспериментировать и с таблицами, которые мы создали в этой статье у себя на локальной машине! В любом случае, удачи в освоении SQL!

Советуем дополнительно почитать по теме: 

Бонус для читателей

Если вам интересно погрузиться в мир ИТ и при этом немного сэкономить, держите наш промокод на курсы Практикума. Он даст вам скидку при оплате, поможет с льготной ипотекой и даст безлимит на маркетплейсах. Ладно, окей, это просто скидка, без остального, но хорошая.

Автор: Ислам Винджиев
Вам может быть интересно
easy