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

В эру цифровых технологий казалось бы старая 50-летняя технология не актуально, но к SQL это не относится. С момента появления в 1974 году его востребованность только растёт, ведь большая доля информации вся информация за исключением мультимедийной, хранится в базах данных. Для обращения к базе данных используют SQL-запросы – или команды, которые позволяют добавлять, удалять, редактировать, фильтровать, сортировать информацию и выполнять десятки других манипуляций. Попрактиковаться в написании запросов можно при помощи интерактивных тренажёров, а ознакомиться с их классификацией, структурой, способами написания и оптимизации – в данной статье.
Интерактивный онлайн-тренажер по SQL: лучшие платформы

Что такое запрос в SQL?

Запросом называют инструкцию системе управления базами данных, в которой описано что нужно сделать. Она состоит из одной строчки, хотя сложные длинные команды могут записывать в несколько строк для удобства чтения кода.

Команду на отображение имён пользователей с таблицы users, которым 30+ лет с сортировкой по имени в алфавитном порядке, можно записать двумя способами:

SELECT name, age FROM users WHERE age > 30 ORDER BY name;

или

SELECT name, age
FROM users
WHERE age > 30
ORDER BY name;

А теперь представьте более сложную инструкцию, записанную в одну строчку.

SELECT u.name, COUNT(o.id) AS order_count, SUM(o.total_amount) AS total_spent
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.status = 'completed'
GROUP BY u.name
HAVING COUNT(o.id) > 5
ORDER BY total_spent DESC;

Какой вариант кода легче понять?

Состав запросов.

  • Ключевые слова — зарезервированные команды SQL (SELECT, FROM, WHERE и т.д.) 
  • Идентификаторы — имена таблиц, колонок, схем.
  • Литералы — конкретные значения (строки, числа, даты).
  • Операторы — символы для сравнения, арифметические и логические действия.
  • Разделители — запятые, скобки, точки с запятой.

Их базовая структура включает до 7 команд:

  • SELECT [модификаторы] список_колонок – ключевое слов.
  • FROM источник_данных – указатель, идентификатор данных – с какой частью таблицы работать: номера, количество строк, например.
  • [WHERE условия_фильтрации] – условие для фильтрации данных.
  • [GROUP BY колонки_группировки] – условие группировки информации по столбцам.
  • [HAVING условия_для_групп] – собирает группы по условию, применяют обычно со следующим оператором.
  • [ORDER BY колонки_сортировки] – способ сортировки: по возрастания или в обратном порядке.
  • [LIMIT количество_записей] – максимальное число первых n записей, если их в таблице больше указанного количества удовлетворяющих условия.

Две первые команды обязательны: SELECT и FROM, остальные – нет.

Пример:

SELECT
    department_id,      -- Выбираем столбец
    COUNT
(*) AS employee_count,      -- Подсчет
    AVG
(salary) AS avg_salary     -- Агрегатная функция среднего
FROM
    employees                   -- Источник данных - таблица
WHERE
    hire_date > '2024-03-11'    -- Фильтр: сотрудники, принятые после указанной даты
GROUP BY
    department_id                 -- Группировка по отделам
HAVING 
    COUNT(*) > 7                 -- Фильтр групп: отделы с >7 сотрудниками
ORDER BY
    avg_salary DESC             -- Сортировка по убыванию средней зарплаты
LIMIT 5;                          -- Только топ-5 отдела

Ничего сложного, даже после беглого знакомства с SQL код становится читаемым и легко понимаемым, тем более он близок к естественным языкам и Python.

Классификация запросов

Команды делят по разным критериям.

Количество используемых таблиц

Исходя из числа задействованных таблиц:

Запросы к одной таблице – базовые операции с данными в конкретной структуре, сущности: выборка, редактирование, фильтрация, удаление, обновление, математические операции: SELECT, GROUP BY, WHERE.

Многотабличные – объединяют содержимое двух и более таблиц при помощи операций JOIN.

  • INNER JOIN: возвращает строки, для которых есть совпадения в обеих таблицах.
  • LEFT JOIN: возвращает строки из левой таблицы и совпадающие строки из правой. Если совпадений нет, правая часть содержит NULL.
  • RIGHT JOIN: аналогично LEFT JOIN, но возвращает все строки из правой таблицы.
  • FULL JOIN: возвращает строки, когда есть совпадение в одной из таблиц.

Пример работы многотабличного SQL-запроса: берёт сотрудников из таблицы employees соединяет с таблицей departments по общему полю  таблиц (3 с первой и 1 со второй) department_id и возвращает список сотрудников с общим отделом. 

SELECT  -- Начало выборки данных
    e.employee_id,      -- ID сотрудника из таблицы employees
    e.first_name,       -- Имя сотрудника
    e.last_name,        -- Фамилия сотрудника
    d.department_name   -- Название отдела из таблицы departments
FROM                   -- Указываем основную таблицу для выборки
    employees e        -- Таблица сотрудников с алиасом 'e' для удобства
INNER JOIN            -- Тип соединения таблиц (внутреннее соединение)
    departments d      -- Таблица отделов с алиасом 'd'
ON                    -- Условие соединения таблиц
    e.department_id = d.department_id;  -- Связь по полю department_id

Подзапросы или вложенные SELECT-запросы. Бывают:

Корреляционными – ссылаются на колонки из внешнего запроса и выполняются для каждой строки внешнего запроса. Это делает их менее эффективными, но иногда незаменимыми для решения сложных задач.

--Поиск последнего заказа каждого клиента:
SELECT 
    customer_id,
    order_id,
    order_date,
    total_amount
FROM orders o1
WHERE order_date = (
    SELECT MAX(order_date)
    FROM orders o2
    WHERE o2.customer_id = o1.customer_id
);

Предикатными – используются в условиях WHERE или HAVING с предикатами IN, ANY, ALL, EXISTS. Они не коррелированы с внешним запросом, выполняются один раз, решают сложные аналитические задачи.
— Поиск продуктов, которые были заказаны в количестве больше среднего:

SELECT
    p.product_id,
    p.product_name,
    p.price
FROM
    products p
WHERE
    p.product_id IN (
        -- Находим товары, в данном случае, заказанные в количестве выше среднего
        SELECT
            oi.product_id
        FROM
            order_items oi
        WHERE
            -- Условие: количество в заказе больше среднего для этого товара
            oi.quantity > (
                -- Подзапрос для расчета среднего количества товара в заказах
                SELECT
                    AVG(quantity)
                FROM
                    order_items
                WHERE
                    product_id = oi.product_id
            )
        GROUP BY
            oi.product_id
        HAVING
            -- Оставляем только товары с более чем 5 такими заказами
            COUNT(*) > 5
    );

Выделяют 5 групп запросов, которые отвечают за определённые аспекты работы с базой данных.

DDL

Data Definition Language – определение данных. Включает основные команды для создания, изменения и удаления структуры базы данных: таблиц, индексов, представлений, схем и других объектов.

CREATE – создание.

— Простой таблицы.

CREATE TABLE employees (
    employee_id INT PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    hire_date DATE,
    salary DECIMAL(10,2),
    department_id INT,
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

— Таблицы с дополнительными ограничениями.

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT NOT NULL,
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    total_amount DECIMAL(12,2) CHECK (total_amount > 0),
    status ENUM('pending', 'processing', 'completed', 'cancelled')
);

— Обычного индекса.

CREATE INDEX idx_employee_email ON employees(email);

— Составного индекса.

CREATE INDEX idx_order_customer_date ON orders (customer_id, order_date);

ALTER – изменение структуры, ADD – добавление.

— Добавление новой колонки

ALTER TABLE employees 
ADD COLUMN phone VARCHAR(20);

— Изменение типа данных колонки

ALTER TABLE employees 
MODIFY COLUMN salary DECIMAL(12,2);

—Переименование колонки

ALTER TABLE employees 
RENAME COLUMN hire_date TO employment_date;

— Добавление ограничения

ALTER TABLE employees 
RENAME COLUMN hire_date TO employment_date;

DROP — удаление объектов.

— Таблицы 

DROP TABLE temp_data;

— Индекса 

DROP INDEX idx_employee_email;

— Представления

 DROP VIEW employee_summary;

— Базы данных

 DROP DATABASE test_database;

ВВД концентрируются на содержимом базы данных, её таблиц. С деланные с их помощью изменения невозможно откатить без резервной копии.

DML

Data Manipulation Language – манипуляции с данными: изменение, обновление, удаление, слияние.

INSERT — добавление.

— Простая вставка 

INSERT INTO employees (first_name, last_name, email, hire_date, salary, department_id)
VALUES (Петр, 'Иванов', petr.ivanov@company.com', '2025-09-12', 65000.00, 1);

— Множественная вставка

INSERT INTO products (name, price, category) VALUES
('Laptop', 1999.99, 'Electronics'), ('Mouse', 26, 'Electronics'), ('Keyboard', 45.50, 'Electronics');

UPDATE – обновление.

— Обновление одной записи

UPDATE employees SET salary = 7000.00, department_id = 2 WHERE employee_id = 1;

DELETE – удаление.

— Удаляет конкретные записи из таблицы

DELETE FROM orders WHERE order_date < ‘2024-11-10’ AND status = ‘cancelled’;

DML, в отличие от DDL-запросов, которые описывают структуру баз данных, работают с её содержимым на более низком уровне.   

DCL 

Data Control Language – запросы управления доступом.

GRANT – предоставление прав.

— На чтение таблицы.

 GRANT SELECT ON employees TO user_analyst;

— На базу данных (все привилегии)

 GRANT ALL PRIVILEGES ON company_db.* TO admin_user;

REVOKE – отзыв прав.

— На обновление данных.

REVOKE UPDATE ON employees FROM junior_developer;

— Отзыв всех прав на таблицу.

 REVOKE ALL PRIVILEGES ON sensitive_data FROM temp_user;

— Создание нового пользователя

CREATE USER ‘new_employee’@’localhost’ IDENTIFIED BY ‘secure_pass’;

— Изменение пароля пользователя 

ALTER USER ‘existing_user’@’localhost’ IDENTIFIED BY ‘new_pass’;

DCL фокусируются на управлении правами пользователей, чем минимизирует риски несанкционированного доступа, изменения структуры, содержимого хранилища.

TCL

Transaction Control Language или запросы управления транзакциями.

TCL предлагает команды для управления транзакциями – логическими единицами работы с базой данных.

BEGIN/START TRANSACTION — начало транзакции.

— Явное начало транзакции 

BEGIN TRANSACTION; 

—Второй вариант

START TRANSACTION;

COMMIT — подтверждение транзакций.

BEGIN TRANSACTION;

INSERT INTO accounts (account_id, balance) VALUES (1001, 1000.00);

— Подтверждение всех изменений

COMMIT;

ROLLBACK – откат транзакции.

BEGIN TRANSACTION;

UPDATE products SET price = price * 2; 

SAVEPOINT – создание точки сохранения.

BEGIN TRANSACTION; 

— Создание нового клиента

INSERT INTO customers (name, email) VALUES ('Test User', 'test@example.com');

SAVEPOINT customer_created;

TCL-запросы управляют транзакциями: начинают, фиксируют и подтверждают их.

DQL

Data Query Language отвечают за извлечения данных из БД. Единственная команда этой категории – SELECT, но она обладает огромной функциональностью и гибкостью.

— Выбор всех колонок из таблицы

 SELECT * FROM employees; 

—Выбор конкретных колонок 

SELECT first_name, last_name, email FROM employees; 

—Условная выборка

SELECT * FROM employees WHERE department = 'IT' AND salary > 50000;

—Подсчет количества сотрудников по департаментам 

SELECT 

department,

COUNT(*) as employee_count,

AVG(salary) as avg_salary,

MAX(salary) as max_salary

 FROM employees

GROUP BY department

HAVING COUNT(*) > 5;

Технически DQL относят к подмножеству DML, но часто выделяют в отдельную категорию из-за крайней важности – SELECT используют чаще любой другой команды.

Сложные запросы

Что делать новичку, когда появляется необходимость составлять сложные запросы?

Просить помощи и старших коллег.
Практиковаться в тренажёрах и на реальных данных.
Использовать нейронные сети. 

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

Напиши сложный SQL-запрос: нужно определить суммарную зарплату молодых сотрудников, принятых начиная с 2024 года, сгруппировав с по отделам.  Дополнительные сведения:

  • отдел — столбец называется department ;
  • столбец с зарплатой — это salary;
  • имена сотрудников — name;
  • дата принятия на работу — date_working.
    В итоге получите готовый запрос:

WITH

— Фильтрация сотрудников, принятых с 2024 года

recent_employees AS (

   SELECT

       department,

       name,

       salary,

       date_working,

       EXTRACT(YEAR FROM date_working) AS hire_year

   FROM

       employees

   WHERE

       date_working >= '2024-01-01'

),

— Расчет статистики по отделам

department_stats AS (

   SELECT

       department,

       COUNT(*) AS employee_count,

       SUM(salary) AS total_salary,

       ROUND(AVG(salary), 2) AS avg_salary,

       MAX(salary) AS max_salary,

       MIN(salary) AS min_salary,

       ROUND(STDDEV(salary), 2) AS salary_stddev

   FROM

       recent_employees

   GROUP BY

       department

),

— Расчет общего среднего по компании

company_stats AS (

   SELECT

       AVG(salary) AS company_avg_salary,

       SUM(salary) AS company_total_salary

   FROM

       recent_employees

)

— Итоговый отчет с расширенной аналитикой

SELECT

   ds.department,

   ds.employee_count,

   ds.total_salary,

   ds.avg_salary,

   ds.max_salary,

   ds.min_salary,

   ds.salary_stddev,

   — Процент от общих расходов на зарплаты

   ROUND((ds.total_salary / cs.company_total_salary) * 100, 2) AS salary_percentage,

   — Сравнение со средним по компании

   ROUND((ds.avg_salary / cs.company_avg_salary) * 100, 2) AS avg_salary_comparison,

   — Список сотрудников в отделе

(SELECT STRING_AGG(name, ', ' ORDER BY salary DESC)
    FROM recent_employees re
    WHERE re.department = ds.department) AS employees_list,

   — Флаг высокооплачиваемых отделов

CASE

       WHEN ds.avg_salary > cs.company_avg_salary * 1.2 THEN 'Высокий'

       WHEN ds.avg_salary > cs.company_avg_salary THEN 'Выше среднего'

       WHEN ds.avg_salary < cs.company_avg_salary THEN 'Ниже среднего'

       ELSE 'Средний'

   END AS salary_level

FROM

   department_stats ds

CROSS JOIN

   company_stats cs

ORDER BY

   ds.total_salary DESC,

   ds.avg_salary DESC;

Итоговый результат всегда можно подкорректировать самому или попросить сделать это нейронную сеть.

Таблица SQL-запросов

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

КатегорияТип запроса/функцииПримеры SQL-запросовОписание
ОсновныеSELECTSELECT name, age FROM usersВыбор данных из таблицы
INSERTINSERT INTO users (name, age) VALUES (‘Иван’, 30)Добавление новых записей
UPDATEUPDATE users SET age=31 WHERE name=’Иван’Обновление записей
DELETEDELETE FROM users WHERE age > 100Удаление записей
СтроковыеUPPER()SELECT UPPER(name) FROM usersПреобразование в верхний регистр
LOWER()SELECT LOWER(email) FROM contactsПреобразование в нижний регистр
CONCAT()SELECT CONCAT(first_name, ‘ ‘, last_name) FROM employeesОбъединение строк
SUBSTRING()SELECT SUBSTRING(phone, 1, 3) FROM clientsИзвлечение части строки
TRIM()SELECT TRIM(address) FROM locationsУдаление пробелов с обеих сторон
Дата/времяNOW()SELECT NOW() AS current_datetimeТекущая дата и время
CURDATE()SELECT CURDATE() AS todayТекущая дата
CURTIME()SELECT CURTIME() AS current_timeТекущее время
YEAR()SELECT YEAR(birth_date) FROM personsИзвлечение года из даты
MONTH()SELECT MONTH(created_at) FROM ordersИзвлечение месяца (1-12)
DAY()SELECT DAY(delivery_date) FROM shipmentsИзвлечение дня месяца
DATE_FORMAT()SELECT DATE_FORMAT(date, ‘%d.%m.%Y’) FROM eventsФорматирование даты
DATEDIFF()SELECT DATEDIFF(end_date, start_date) FROM projectsРазница между датами в днях
Агрегатные функцииCOUNT()SELECT COUNT(*) FROM usersПодсчёт количества строк
SUM()SELECT SUM(salary) FROM employeesСумма значений
AVG()SELECT AVG(price) FROM productsСреднее значение
СоединенияJOINSELECT u.name, o.date FROM users u JOIN orders o ON u.id=o.user_idОбъединение таблиц

SQL для работы с данными использует запросы или команды. Каждая из них нацелена на совершение действий с информацией, её структурой или правами доступа.

Максим Корень
Максим Корень

Контент-менеджер, копирайтер с увлечениями и образованием в сфере IT. Года с 2016 пишу SEO-оптимизированные статьи преимущественно на тему электроники, высоких технологий и программного обеспечения. Имею опыт в создании, наполнении контентом и продвижении сайтов, монтаже видео, программировании, модостроении.

Мы будем рады услышать ваши мысли

ОСТАВИТЬ ОТВЕТ

Реклама. Информация о рекламодателе по ссылкам в статье.
eddu.pro
Logo
Зарегистрировать новый аккаунт