Несложный SQL-запрос с условием EXISTS может сэкономить много времени при работе с базами данных. В этой статье мы подробно разберем, что такое оператор EXISTS в MySQL, когда и как его использовать на практике. Вы узнаете конкретные кейсы применения EXISTS в SELECT, INSERT и других типах запросов.
Что такое оператор EXISTS в MySQL
EXISTS - это логический оператор в SQL, который используется для проверки существования записей в таблице по определенному условию. Он работает в паре с подзапросом (subquery):
SELECT * FROM table1 WHERE EXISTS (SELECT * FROM table2 WHERE condition);
Если подзапрос вернет хотя бы одну строку, EXISTS вернет значение true, и запись из внешнего запроса будет включена в результирующую выборку. Если подзапрос не вернет ни одной строки - значение будет false, и запись пропускается.
В чем преимущество EXISTS перед другими операторами фильтрации, например = или IN?
- EXISTS работает быстрее, так как возвращает только true/false, а не набор строк
- Проще писать запросы с EXISTS при работе с данными из нескольких таблиц
EXISTS часто используется вместе с коррелированными подзапросами. Это такие подзапросы, которые зависят от строки во внешнем запросе. Например, мы можем проверить наличие заказов для каждого покупателя:
SELECT * FROM customers c WHERE EXISTS (SELECT * FROM orders o WHERE o.customer_id = c.id);
То есть для каждого customer_id из внешней таблицы customers подзапрос будет искать связанные записи в таблице orders. Если найдет - вернет true, если нет - false. И в зависимости от этого конкретная запись покупателя попадет в итоговую выборку или нет.
Когда использовать EXISTS в MySQL запросах
Оператор EXISTS в MySQL можно использовать в разных ситуациях, например:
- Для проверки существования связанных данных в других таблицах при SELECT запросах:
SELECT * FROM products p WHERE EXISTS (SELECT * FROM order_items oi WHERE oi.product_id = p.id)
- В операторах INSERT, UPDATE, DELETE - для вставки, изменения или удаления данных по определенным условиям:
INSERT INTO archive_customers SELECT * FROM customers WHERE NOT EXISTS (SELECT * FROM orders WHERE customer_id = customers.id)
- При создании хранимых процедур и триггеров - чтобы проверить, существует ли уже такой объект с нужным именем:
CREATE PROCEDURE my_proc() BEGIN ... END IF NOT EXISTS (SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_NAME = 'my_proc') BEGIN -- create procedure END
Как видите, с помощью оператора EXISTS можно гибко фильтровать данные в MySQL, экономя время на написание сложных условий.
Примеры использования EXISTS в MySQL
Mysql Exists: давайте рассмотрим несколько конкретных случаев использования EXISTS на практике.
Запрос к одной таблице
Самый простой вариант - запрос EXISTS к одной таблице. Например, найдем всех поставщиков, у которых есть товары дешевле 20 долларов:
SELECT * FROM suppliers WHERE EXISTS (SELECT * FROM products WHERE supplier_id = suppliers.id AND price < 20);
Подзапрос будет выполнен для каждой строки внешней таблицы suppliers и проверит наличие связанного товара по supplier_id.
Запрос к нескольким таблицам
Чаще же бывают случаи с участием данных из нескольких таблиц. Например, запрос покупателей, у которых были заказы:
SELECT * FROM customers WHERE EXISTS (SELECT * FROM orders WHERE customer_id = customers.id);
Здесь сопоставление идет по полю customer_id между таблицами customers и orders.
Подзапросы с группировкой и агрегатными функциями
Можно использовать EXISTS и с более сложными подзапросами, например с GROUP BY. Посчитаем количество покупателей в каждом городе, где было сделано больше 10 заказов:
SELECT city, COUNT(*) FROM customers WHERE EXISTS (SELECT city FROM orders WHERE customer_id = customers.id GROUP BY city HAVING COUNT(*) > 10) GROUP BY city;
Здесь внешний запрос группирует покупателей по городам, а подзапрос находит города с более чем 10 заказами.
Сравнение производительности EXISTS и IN
Для выборки связанных данных часто используют оператор IN. Но во многих случаях EXISTS работает быстрее. Например, посмотрим время выполнения этих двух запросов:
Запрос | Время выполнения |
| 0.56 sec |
| 0.03 sec |
Как видим, запрос с EXISTS выполнился почти в 20 раз быстрее! Так что при выборе между этими двумя вариантами стоит обращать внимание на производительность.