Уроки модуля (4/4)
Запрос внутри другого: подзапросы
Вы научились извлекать, фильтровать, группировать, объединять и преобразовывать. Там это еще одна фундаментальная идея: помещение запроса внутрь другого. Это называются подзапросами и позволяют отвечать на вопросы. например "кто зарабатывает выше среднего?" или "в каких отделах есть кто-то назначено на проект?".
Основной синтаксис
Подзапрос — это SELECT, заключенный в круглые скобки и используемый вместо одного
значение или список значений в другом запросе:
-- Find who earns MORE THAN THE COMPANY AVERAGE:
SELECT first_name, last_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);Сначала движок выполняет подзапрос — SELECT AVG(salary) FROM employees.
возвращает один номер — а затем использует это число во внешнем WHERE
как будто ты это написал от руки. Именно в этом преимущество: вы делаете
не нужно знать среднее значение заранее, SQL вычисляет его за вас.
Три наиболее распространенных «типа»
1. Подзапрос, возвращающий одно значение
Пример выше: подзапрос создает одну строку, один столбец (называемый
скаляр). Вы используете его с =, >, < и так далее.
-- Employee with the highest salary:
SELECT first_name, last_name
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);2. Подзапрос, возвращающий список
Подзапрос создает один столбец, много строк. Вы используете его с
IN (...):
-- Departments that have at least one employee:
SELECT name
FROM departments
WHERE id IN (SELECT DISTINCT department_id
FROM employees
WHERE department_id IS NOT NULL);3. Подзапрос в виде «таблицы» (FROM)
Подзапрос также может заменить таблицу в FROM. Это полезно
предварительно вычислить агрегаты, а затем отфильтровать или объединить их:
-- Departments with average salary above 40000:
SELECT d.name, medie.stipendio_medio
FROM departments AS d
JOIN (SELECT department_id, AVG(salary) AS stipendio_medio
FROM employees
GROUP BY department_id) AS medie
ON d.id = medie.department_id
WHERE medie.stipendio_medio > 40000;Подзапрос или ПРИСОЕДИНЕНИЕ? Когда какой использовать
Часто тот же результат можно получить с помощью JOIN или подзапроса.
Эмпирическое правило:
– Чтобы фильтровать строки одной таблицы на основе свойства другой.
("сотрудники, отделы которых..."), IN (subquery) очень читаем.
– Чтобы объединить столбцы из нескольких таблиц в результате, используйте JOIN.
– Чтобы вычислить совокупный показатель и использовать его в качестве порогового значения ("выше
средний"), скалярный подзапрос является естественным выбором.
На практике вы увидите и то, и другое: механизм SQL часто оптимизирует их одинаково. путь. Выберите форму, которая читается лучше всего.
Попробуйте это
Найдите имя (first_name), фамилию (last_name) и зарплату (salary) сотрудников, которые зарабатывают СТРОГО больше, чем в среднем по компании. Три колонки.
Показать подсказку
Заменять ? с подзапросом SELECT AVG(salary) FROM сотрудников — он возвращает одно число, которое можно использовать в качестве порога.
Решение доступно после 3 попыток
Обзор упражнения
Перечислите названия (departments.name) отделов, в которых есть хотя бы один сотрудник с зарплатой строго больше 50 000. Используйте подзапрос с IN. Порядок в алфавитном порядке.
Показать подсказку
Внутренний подзапрос возвращает идентификаторы отделов, в которых есть сотрудники с зарплатой > 50000. Затем WHERE id IN (...) во внешнем запросе.
Решение доступно после 3 попыток