Вложенный запрос MySQL полное руководство с примерами
Вложенный запрос MySQL (subquery) — это SQL-запрос внутри другого запроса. Вложенные запросы MySQL используются для получения данных, которые затем применяются в основном запросе.
В этой статье разберем:
- Что такое вложенный запрос MySQL
- Простые примеры вложенных запросов
- Вложенный запрос в WHERE
- Вложенный запрос в SELECT
- Вложенный запрос в FROM
- EXISTS и NOT EXISTS
- Вложенные запросы с JOIN
- Вложенные запросы UPDATE/DELETE/INSERT
Что такое вложенный запрос MySQL
Вложенный запрос MySQL — это запрос внутри другого SQL запроса.
Общий синтаксис:
SELECT column_name
FROM table_name
WHERE column_name = (
SELECT column_name
FROM table_name
);
Внутренний запрос выполняется первым, затем результат передается во внешний запрос.
Пример таблиц для вложенных запросов
Допустим, у нас есть таблицы:
Таблица users:
id | name | role_id 1 | Ivan | 1 2 | Alex | 2 3 | Oleg | 1
Таблица roles:
id | role_name 1 | admin 2 | user
Простой вложенный запрос MySQL
Найти всех администраторов:
SELECT *
FROM users
WHERE role_id = (
SELECT id
FROM roles
WHERE role_name = 'admin'
);
Как работает:
- Внутренний запрос находит id роли admin
- Внешний запрос получает пользователей с этим id
Вложенный запрос MySQL в WHERE
Самый популярный вариант использования вложенного запроса — в WHERE. Но чаще всего вы не будете писать вручную искомый текст, а будете подставлять какую либо переменную. По этой теме мы уже писали в одной из прошлой статье, о том, что такое mysql инъекция и как защитить сайт.
Пример:
SELECT *
FROM products
WHERE category_id = (
SELECT id
FROM categories
WHERE name = 'Ноутбуки'
);
Этот запрос:
- Получает ID категории
- Находит товары в этой категории
Вложенный запрос MySQL с IN
Если вложенный запрос возвращает несколько значений, используется IN:
SELECT *
FROM users
WHERE role_id IN (
SELECT id
FROM roles
WHERE role_name IN ('admin', 'manager')
);
Этот запрос найдет:
- Администраторов
- Менеджеров
Вложенный запрос MySQL с NOT IN
Можно исключить данные:
SELECT *
FROM users
WHERE role_id NOT IN (
SELECT id
FROM roles
WHERE role_name = 'admin'
);
Этот запрос вернет всех пользователей кроме администраторов.
Вложенный запрос MySQL в SELECT
Вложенные запросы можно использовать в SELECT.
Пример:
SELECT
name,
(
SELECT role_name
FROM roles
WHERE roles.id = users.role_id
) AS role
FROM users;
Результат:
Ivan | admin Alex | user Oleg | admin
Вложенный запрос MySQL в FROM
Вложенный запрос можно использовать как временную таблицу.
Пример:
SELECT *
FROM (
SELECT *
FROM users
WHERE role_id = 1
) AS admins;
Этот запрос:
- Создает временную таблицу
- Затем выполняет запрос к ней
Вложенный запрос MySQL с EXISTS
EXISTS проверяет наличие записей.
Пример:
SELECT *
FROM users
WHERE EXISTS (
SELECT *
FROM orders
WHERE orders.user_id = users.id
);
Этот вложенный запрос:
- Найдет пользователей
- У которых есть заказы
Пример с NOT EXISTS:
SELECT *
FROM users
WHERE NOT EXISTS (
SELECT *
FROM orders
WHERE orders.user_id = users.id
);
Этот запрос найдет пользователей без заказов.
Коррелированный вложенный запрос MySQL
Коррелированный запрос зависит от внешнего запроса.
Пример:
SELECT *
FROM users u
WHERE salary > (
SELECT AVG(salary)
FROM users
WHERE department_id = u.department_id
);
Этот запрос:
- Сравнивает зарплату
- С средней зарплатой отдела
Вложенный запрос MySQL с агрегатными функциями
Пример, найти пользователей с максимальной зарплатой:
SELECT *
FROM users
WHERE salary = (
SELECT MAX(salary)
FROM users
);
Вложенный запрос MySQL с COUNT
Этот запрос найдет пользователей с более чем 5 заказами
SELECT *
FROM users
WHERE id IN (
SELECT user_id
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 5
);
Вложенный запрос MySQL с JOIN
Иногда вложенные запросы заменяются JOIN. Вложенный запрос:
SELECT *
FROM users
WHERE role_id = (
SELECT id
FROM roles
WHERE role_name = 'admin'
);
А теперь через JOIN:
SELECT users.* FROM users JOIN roles ON users.role_id = roles.id WHERE roles.role_name = 'admin';
JOIN часто работает быстрее.
Вложенные запросы MySQL UPDATE/DELETE/INSERT
Вложенные запросы в mysql можно применять не только для получения информации, но и в других случаях при манипуляции с данными. Подобные действия не всегда имеют место быть в разработке, но для информации будет полезным.
Вложенный запрос MySQL UPDATE
Можно использовать вложенный запрос mysql при обновлении данных:
UPDATE users
SET role_id = (
SELECT id
FROM roles
WHERE role_name = 'manager'
)
WHERE name = 'Ivan';
Вложенный запрос MySQL DELETE
Например, можно произвести удаление пользователя с вложенным запросом mysql:
DELETE FROM users
WHERE id IN (
SELECT user_id
FROM banned_users
);
Вложенный запрос MySQL INSERT
Пример вложенного запроса через insert:
INSERT INTO archive_users
SELECT *
FROM users
WHERE id IN (
SELECT user_id
FROM old_users
);
Оптимизация вложенных запросов MySQL
Ранее мы уже писали в одной из статей про mysql оптимизацию запросов и ускорение работы. Некоторые советы по использованию вложенных запросов:
- Используйте индексы
- Избегайте вложенных запросов в больших таблицах
- Используйте JOIN при необходимости
- Ограничивайте результат LIMIT
Пример такого запроса:
SELECT *
FROM users
WHERE id = (
SELECT user_id
FROM orders
LIMIT 1
);
Вложенный запрос MySQL — это мощный инструмент для работы с данными. Он позволяет создавать сложные SQL запросы, фильтровать данные и выполнять аналитику.
Основные типы вложенных запросов:
- WHERE
- SELECT
- FROM
- EXISTS
- UPDATE
- DELETE
Есть еще более интересные вариации запросов, о них мы писали в одной из статей: mysql select запросы DISTINCT, GROUP, LIKE, UNION. Используйте вложенные запросы MySQL для гибкой работы с базой данных и оптимизации SQL запросов.