Подзапросы с IN, EXISTS, ANY, ALL

🕵️‍♂️ Что такое подзапросы и зачем они нужны?

Подзапросы — это SQL-запросы, вложенные внутрь других запросов. Представьте себе матрёшку: внешний запрос — это большая кукла, а внутри неё спрятаны маленькие. 🪆

Основные сценарии использования:

  • Фильтрация данных (в WHERE)
  • Создание вычисляемых столбцов (в SELECT)
  • Формирование временных таблиц (в FROM)
-- Пример простого подзапроса
SELECT name 
FROM employees
WHERE department_id IN (SELECT id FROM departments WHERE location = 'New York');

🔍 IN: Проверка принадлежности множеству

Оператор IN проверяет, совпадает ли значение с хотя бы одним элементом из списка или результата подзапроса. Это как спросить: «А этот товар есть в моём списке покупок?» 🛒

📌 Пример 1: Простое использование

SELECT product_name 
FROM products
WHERE category_id IN (1, 3, 7);  -- Только категории 1, 3 или 7

📌 Пример 2: С подзапросом

SELECT employee_name 
FROM employees
WHERE department_id IN (
    SELECT department_id 
    FROM departments 
    WHERE budget > 1000000  -- Только сотрудники из «богатых» отделов
);

💡 Лайфхак: NOT IN работает аналогично, но проверяет отсутствие значения в списке.


🎯 EXISTS: Проверка существования строк

EXISTS возвращает TRUE, если подзапрос вернул хотя бы одну строку. Это как звонок другу: «Ты ещё в офисе?» — если ответ «да», значит можно заходить. ☎️

📌 Пример 1: Базовый сценарий

SELECT supplier_name
FROM suppliers
WHERE EXISTS (
    SELECT 1 
    FROM products 
    WHERE products.supplier_id = suppliers.supplier_id 
    AND price < 10  -- Поставщики, у которых есть товары дешевле 10
);

📌 Пример 2: С корреляцией

SELECT department_name
FROM departments d
WHERE EXISTS (
    SELECT 1 
    FROM employees e 
    WHERE e.department_id = d.department_id 
    AND salary > 100000  -- Отделы, где есть хотя бы один «топовый» сотрудник
);

🔥 Важно: В отличие от IN, EXISTS обычно работает быстрее на больших таблицах, так как прекращает проверку при первом совпадении.


🏆 ANY/SOME и ALL: Сравнение с набором значений

Эти операторы позволяют сравнивать значение с каждым элементом подзапроса. Разберём на примерах!

🌈 ANY/SOME: «Хотя бы один»

То же самое, что IN, но с возможностью использования операторов сравнения.

SELECT product_name
FROM products
WHERE price > ANY (
    SELECT price 
    FROM products 
    WHERE category = 'Premium'  -- Товары дороже хотя бы одного премиум-товара
);

🏋️‍♂️ ALL: «Все без исключения»

SELECT employee_name
FROM employees
WHERE salary > ALL (
    SELECT salary 
    FROM employees 
    WHERE department = 'Support'  -- Зарплата выше ВСЕХ сотрудников поддержки
);

💎 Золотое правило:

  • = ANY эквивалентен IN
  • <> ALL эквивалентен NOT IN

🧩 Комбинируем подходы: Продвинутые примеры

📌 Пример 1: EXISTS + агрегация

SELECT customer_id
FROM orders o
WHERE EXISTS (
    SELECT 1
    FROM order_details od
    WHERE od.order_id = o.order_id
    GROUP BY od.order_id
    HAVING SUM(od.quantity) > 10  -- Заказы с общим количеством товаров > 10
);

📌 Пример 2: ALL с подзапросом

SELECT name
FROM students
WHERE gpa > ALL (
    SELECT gpa
    FROM students
    WHERE graduation_year = 2020  -- Студенты с GPA выше всех выпускников 2020 года
);

🚀 Оптимизация подзапросов: ТОП-3 совета

  1. Индексы — убедитесь, что поля в условиях соединения проиндексированы
  2. EXISTS vs IN — для проверки существования EXISTS обычно эффективнее
  3. LIMIT в подзапросах — если нужно проверить только наличие, добавьте LIMIT 1

🏁 Закрепляем знания

Попробуйте решить:

  1. Найти клиентов, которые покупали ВСЕ товары из категории «Электроника»
  2. Вывести продукты, которые дороже СРЕДНЕЙ цены в их категории
  3. Найти отделы, где НЕТ сотрудников младше 30 лет
-- Подсказка для первого задания:
SELECT customer_id
FROM customer_products cp
WHERE NOT EXISTS (
    SELECT 1 
    FROM products p 
    WHERE p.category = 'Electronics'
    AND NOT EXISTS (
        SELECT 1 
        FROM purchases pu 
        WHERE pu.product_id = p.product_id 
        AND pu.customer_id = cp.customer_id
    )
);
Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty