Вложенные подзапросы SQL
Вложенные подзапросы
Подзапрос может быть вложен в другие подзапросы. SQL имеет возможность вкладывать запросы друг в друга. Подзапрос - это оператор SELECT, который вложен в другой оператор SELECT и возвращает промежуточные результаты. SQL сначала выполняет самый внутренний подзапрос, затем следующий уровень. Смотрите следующие примеры:
Пример -1: вложенные подзапросы
Если мы хотим извлечь этот уникальный идентификатор job_id и его среднюю зарплату из таблицы сотрудников, у которой уникальный job_id имеет зарплату меньше чем (максимальное из средних значений min_salary для каждого уникального job_id из таблицы заданий, для которой job_id есть в списке, выбирая из ( таблица job_history, которая находится в отделе_id 50 и 100)), можно использовать следующий оператор SQL:
Пример таблицы: сотрудники
Пример таблицы: вакансии
Код SQL:
SELECT job_id,AVG(salary)
FROM employees
GROUP BY job_id
HAVING AVG(salary)<
(SELECT MAX(AVG(min_salary))
FROM jobs
WHERE job_id IN
(SELECT job_id FROM job_history
WHERE department_id
BETWEEN 50 AND 100)
GROUP BY job_id);
Приведенный выше код выполняется в Oracle 11g Express Edition.
или же
SELECT job_id,AVG(salary)
SELECT job_id,AVG(salary)
FROM employees
GROUP BY job_id
HAVING AVG(salary)<
(SELECT MAX(myavg) from (select job_id,AVG(min_salary) as myavg
FROM jobs
WHERE job_id IN
(SELECT job_id FROM job_history
WHERE department_id
BETWEEN 50 AND 100)
GROUP BY job_id) ss);
Приведенный выше код выполняется в PostgreSQL 9.3
Выход
JOB_ID AVG (SALARY) ---------- ----------- IT_PROG 5760 AC_ACCOUNT 8300 ST_MAN 7280 AD_ASST 4400 SH_CLERK 3215 FI_ACCOUNT 7920 PU_CLERK 2780 SA_REP 8350 MK_REP 6000 ST_CLERK 2785 HR_REP 6500
Объяснение:
Этот пример содержит три запроса: вложенный подзапрос, подзапрос и внешний запрос. Эти части запросов выполняются в указанном порядке.
Давайте разберем пример на три части и проследим за возвращенными результатами.
Сначала вложенный подзапрос следующим образом:
Код SQL:
SELECT job_id FROM job_history
WHERE department_id
BETWEEN 50 AND 100;
Этот вложенный подзапрос извлекает job_id (ы) из таблицы job_history, которая находится в отделе_id 50 и 100.
Вот вывод.
Выход:
JOB_ID ---------- ST_CLERK ST_CLERK IT_PROG SA_REP SA_MAN AD_ASST AC_ACCOUNT
Вот графическое представление того, как получается вышеприведенный вывод.
Теперь подзапрос, который получает выходные данные из вложенного подзапроса, указанного выше.
SELECT MAX(AVG(min_salary))
FROM jobs WHERE job_id
IN(.....output from the nested subquery......)
GROUP BY job_id
Внутренний подзапрос работает следующим образом:
Код SQL:
SELECT MAX(AVG(min_salary))
FROM jobs
WHERE job_id
IN(
'ST_CLERK','ST_CLERK','IT_PROG',
'SA_REP','SA_MAN','AD_ASST', '
AC_ACCOUNT')
GROUP BY job_id;
Подзапрос возвращает максимум средних значений min_salary для каждого уникального возврата job_id (т. Е. «ST_CLERK», «ST_CLERK», «IT_PROG», «SA_REP», «SA_MAN», «AD_ASST», «AC_ACCOUNT») по предыдущему подзапросу.
Вот вывод:
Выход:
MAX (AVG (MIN_SALARY)) -------------------- 10000
Вот графическое представление того, как возвращается вышеприведенный вывод.
Теперь внешний запрос, который получает выходные данные из подзапроса и который также получает выходные данные из вложенного подзапроса, указанного выше.
SELECT job_id,AVG(salary)
FROM employees
GROUP BY job_id
HAVING AVG(salary)<
(.....output from the subquery(
output from the nested subquery)......)
Внешний запрос внутренне работает следующим образом:
Код SQL:
SELECT job_id,AVG(salary)
FROM employees
GROUP BY job_id
HAVING AVG(salary)<10000;
Внешний запрос возвращает job_id, среднюю зарплату сотрудников, которая меньше максимальной средней min_salary, возвращенной предыдущим запросом.
Выход:
JOB_ID AVG (SALARY) ---------- ----------- IT_PROG 5760 AC_ACCOUNT 8300 ST_MAN 7280 AD_ASST 4400 SH_CLERK 3215 FI_ACCOUNT 7920 PU_CLERK 2780 SA_REP 8350 MK_REP 6000 ST_CLERK 2785 HR_REP 6500
Пример -2: вложенные подзапросы
Вот еще один вложенный пример подзапроса.
Пример таблицы: заказы
Образец таблицы: клиент
Пример таблицы: агенты
Код SQL:
SELECT ord_num,ord_date,ord_amount,advance_amount
FROM orders
WHERE ord_amount>2000
AND ord_date<'01-SEP-08'
AND ADVANCE_AMOUNT <
ANY(SELECT OUTSTANDING_AMT
FROM CUSTOMER
WHERE GRADE=3
AND CUST_COUNTRY<>'India'
AND opening_amt<7000
AND EXISTS
(SELECT *
FROM agents
WHERE commission<.12));
Выход:
ORD_NUM ORD_DATE ORD_AMOUNT ADVANCE_AMOUNT ---------- --------- ---------- -------------- 200130 30-июл-08 2500 400 200127 20-июл-08 2500 400 200110 15-АПР-08 3000 500 200105 18-июл-08 2500 500 200129 20-июл-08 2500 500 200108 15-ФЕВ-08 4000 600 200113 10-ИЮНЬ-08 4000 600 200106 20-АПР-08 2500 700 200109 30-ИЮЛ-08 3500 800 200107 30 августа 2008 года 4500 900 200101 15-ИЮЛ-08 3000 1000 200128 20-ИЮЛЬ-08 3500 1500 200114 15 августа 2008 года 3500 2000
Объяснение:
Последний внутренний запрос извлекает строки из таблицы операторов, комиссионные которых меньше 0,12%.
Второй последний внутренний запрос возвращает непогашенную сумму тем клиентам, которые относятся к 3-му классу и не принадлежат к стране Индия, а их начальная сумма открытия составляет менее 7000, и их агенты должны были получить комиссионное вознаграждение менее 0,12%.
Внешний запрос возвращает ord_num, ord_date, ord_amount, advance_amount для тех заказов из таблицы заказов, у которых ord_amount больше 2000 и ord_date до '01 -sep-08 ', и сумма аванса может быть непогашенной суммой для тех клиентов, которые находятся в классе 3 и не принадлежит к стране Индия, и там депонированная сумма открытия составляет менее 7000, и их агенты должны были заработать комиссию менее чем .12%.
Давайте разберем код и проанализируем, что происходит во внутреннем запросе. Вот первый код внутреннего запроса с выводом:
Код SQL:
SELECT *
FROM agents
WHERE commission<.12;
Выход:
AGENT_CODE AGENT_NAME WORKING_AREA COMMISSION PHONE_NO COUNTRY ---------- --------------- ----------------- -------- - --------------- --------- A009 Бенджамин Хэмпшир .11 008-22536178 А002 Мукеш Мумбаи .11 029-12358964
Вот второй код внутреннего запроса (включая первый) с выводом:
Код SQL:
SELECT OUTSTANDING_AMT
FROM CUSTOMER
WHERE GRADE=3
AND CUST_COUNTRY<>'India'
AND opening_amt<7000
AND EXISTS(
SELECT *
FROM agents
WHERE commission<.12);
Выход:
OUTSTANDING_AMT --------------- 6000 3000 5000
Смотрите нашу базу данных моделей
Упражнения по SQL
- Упражнения по SQL, практика, решение
- SQL Получить данные из таблиц [33 Упражнения]
- Булевы и реляционные операторы SQL [12 упражнений]
- Подстановочные знаки SQL и специальные операторы [22 упражнения]
- Агрегатные функции SQL [25 упражнений]
- Вывод запроса форматирования SQL [10 упражнений]
- SQL-запросы к нескольким таблицам [7 упражнений]
- ФИЛЬТРАЦИЯ И СОРТИРОВКА в базе данных персонала [38 упражнений]
- SQL СОЕДИНЯЕТ
- SQL ПОДПИСИ
- SQL Union [9 упражнений]
- SQL View [16 упражнений]
- Управление учетными записями пользователей SQL [16 упражнение]
- База данных фильмов
- ОСНОВНЫЕ запросы к базе данных фильмов [10 упражнений]
- ПОДПИСКИ на фильм База данных [16 упражнений]
- ПРИСОЕДИНЯЕТСЯ к базе данных фильма [24 упражнения]
- Футбольная база
- Вступление
- ОСНОВНЫЕ запросы по футболу базы данных [29 упражнений]
- ПОДПИСКИ по футбольной базе данных [33 упражнения]
- База данных больницы
- База данных сотрудников
- ОСНОВНЫЕ запросы к базе данных сотрудников [115 упражнений]
- БРОНИРОВАНИЕ на сотрудника База данных [77 Упражнения]
- Еще не все!
Хотите улучшить вышеуказанную статью? Вносите свои заметки / комментарии / примеры через Disqus.
Предыдущая: коррелированные подзапросы с использованием псевдонимов
Далее: Союз
Новый контент: Composer: менеджер зависимостей для PHP , R программирования