Перейти к основному содержимому
Модуль 4 · Урок 4 из 416/57 в курсе~12 min
Уроки модуля (4/4)

Запрос внутри другого: подзапросы

Вы научились извлекать, фильтровать, группировать, объединять и преобразовывать. Там это еще одна фундаментальная идея: помещение запроса внутрь другого. Это называются подзапросами и позволяют отвечать на вопросы. например "кто зарабатывает выше среднего?" или "в каких отделах есть кто-то назначено на проект?".

Основной синтаксис

Подзапрос — это SELECT, заключенный в круглые скобки и используемый вместо одного значение или список значений в другом запросе:

SQL
-- 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. Подзапрос, возвращающий одно значение

Пример выше: подзапрос создает одну строку, один столбец (называемый скаляр). Вы используете его с =, >, < и так далее.

SQL
-- Employee with the highest salary:
SELECT first_name, last_name
FROM   employees
WHERE  salary = (SELECT MAX(salary) FROM employees);

2. Подзапрос, возвращающий список

Подзапрос создает один столбец, много строк. Вы используете его с IN (...):

SQL
-- 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. Это полезно предварительно вычислить агрегаты, а затем отфильтровать или объединить их:

SQL
-- 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 часто оптимизирует их одинаково. путь. Выберите форму, которая читается лучше всего.

Попробуйте это

Упражнение#sql.m4.l4.e1
Попыток: 0Загрузка…

Найдите имя (first_name), фамилию (last_name) и зарплату (salary) сотрудников, которые зарабатывают СТРОГО больше, чем в среднем по компании. Три колонки.

Загрузка редактора…
Показать подсказку

Заменять ? с подзапросом SELECT AVG(salary) FROM сотрудников — он возвращает одно число, которое можно использовать в качестве порога.

Решение доступно после 3 попыток

Обзор упражнения

Упражнение#sql.m4.l4.e2
Попыток: 0Загрузка…

Перечислите названия (departments.name) отделов, в которых есть хотя бы один сотрудник с зарплатой строго больше 50 000. Используйте подзапрос с IN. Порядок в алфавитном порядке.

Загрузка редактора…
Показать подсказку

Внутренний подзапрос возвращает идентификаторы отделов, в которых есть сотрудники с зарплатой > 50000. Затем WHERE id IN (...) во внешнем запросе.

Решение доступно после 3 попыток