Подзапросы в FROM: временные таблицы в запросе

Когда подзапросы в FROM — это сила 💪

Подзапросы в FROM — это как волшебный портал в мир SQL: вы создаёте временную таблицу прямо внутри запроса и используете её, как обычную. Это мощный инструмент для:

  • Разбивки сложных запросов на понятные шаги.
  • Агрегации данных перед дальнейшим анализом.
  • Создания «виртуальных» таблиц на лету.

👉 Важно: временная таблица из подзапроса существует только во время выполнения запроса!


Базовый синтаксис: просто, как дважды два

SELECT 
    временная_таблица.поле1,
    временная_таблица.поле2
FROM (
    -- Здесь ваш подзапрос, который создаёт временную таблицу  
    SELECT 
        поле1,
        поле2 
    FROM исходная_таблица
    WHERE условие
) AS временная_таблица  -- Алиас обязателен!

🔹 Почему алиас? Без него SQL не поймёт, как обращаться к временной таблице.


Пример: средняя зарплата по отделам после фильтрации

Допустим, у нас есть таблица employees:

id name department salary
1 Иван IT 100000
2 Мария HR 80000
3 Алекс IT 110000
4 Ольга HR 75000

Задача: найти среднюю зарплату по отделам, но только для сотрудников с зарплатой > 80 000.

Решение с подзапросом в FROM:

SELECT 
    dep_stats.department,
    AVG(dep_stats.salary) AS avg_salary
FROM (
    SELECT 
        department, 
        salary
    FROM employees
    WHERE salary > 80000
) AS dep_stats
GROUP BY dep_stats.department;

Результат:

department avg_salary
IT 105000

🔍 Что произошло?
1. Подзапрос создал временную таблицу dep_stats только с сотрудниками, у которых salary > 80000.
2. Внешний запрос сгруппировал данные по отделам и посчитал среднюю зарплату.


Вложенные подзапросы: когда нужно углубиться

Можно использовать несколько уровней вложенности (но без фанатизма!):

SELECT 
    final_data.department,
    final_data.max_salary
FROM (
    SELECT 
        department,
        MAX(salary) AS max_salary
    FROM (
        SELECT 
            department, 
            salary
        FROM employees
        WHERE name LIKE 'А%'  -- Только имена на "А"
    ) AS filtered_employees
    GROUP BY department
) AS final_data
WHERE final_data.max_salary > 90000;

📌 Совет от Данилы Бежина: Если вложенность больше 2-3 уровней, возможно, стоит вынести логику в CTE (Common Table Expressions).


Подзапросы + JOIN: комбо-удар 🥋

Временные таблицы можно джойнить с другими:

SELECT 
    e.name,
    e.salary,
    dept_stats.avg_salary
FROM employees e
JOIN (
    SELECT 
        department,
        AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department
) AS dept_stats ON e.department = dept_stats.department;

Результат:

name salary avg_salary
Иван 100000 105000
Мария 80000 77500
Алекс 110000 105000
Ольга 75000 77500

🎯 Фишка: теперь у каждого сотрудника есть информация о средней зарплате в его отделе!


Ограничения и подводные камни

  1. Производительность: сложные подзапросы могут замедлить запрос.
  2. Читаемость: много вложенных подзапросов усложняют понимание кода.
  3. Алиасы: если забудете дать имя временной таблице — получите ошибку.

💡 Простое правило: если подзапрос в FROM занимает больше 10 строк — подумайте о CTE или временной таблице.


Практика: решаем реальную задачу

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

SELECT 
    department,
    SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) > (
    SELECT AVG(total_dept_salary)
    FROM (
        SELECT 
            department,
            SUM(salary) AS total_dept_salary
        FROM employees
        GROUP BY department
    ) AS salary_stats
);

Разбор:
1. Вложенный подзапрос считает суммарные зарплаты по отделам.
2. Внешний подзапрос вычисляет среднее из этих сумм.
3. Основной запрос фильтрует отделы через HAVING.

Вуаля! Теперь вы мастер подзапросов в FROM. 🚀

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео