280 likes | 486 Views
ПОДЗАПРОСЫ. Подзапрос. Главный запрос. Синтаксис команды Select Select… From… Where…. Синтаксис Select (Select… From… Where…). Что такое подзапрос?. Подзапрос - это команда SELECT, вложенная в предложение другой команды SQL. Подзапросы: синтаксис. SELECT select_list FROM table
E N D
Подзапрос Главный запрос Синтаксис команды Select Select… From… Where… Синтаксис Select (Select… From… Where…) Что такое подзапрос? Подзапрос - это команда SELECT, вложенная в предложение другой команды SQL.
Подзапросы: синтаксис SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table); • Подзапрос выполняется до выполнения главного запроса. • Результат подзапроса используется главным внешним запросом.
Указания по использованию подзапросов • Подзапрос должен быть заключен в скобки. • В подзапросах используются операторы сравнения двух типов: однострочные и многострочные. • Подзапрос должен находиться справа от оператора. • Подзапросы могут использоваться во многих командах SQL. • Подзапросы не могут содержать предложение ORDER BY.
ПРЕДЛОЖЕНИЯ КОМАНДЫ SELECT, В КОТОРЫХ ИСПОЛЬЗУЮТСЯ ПОДЗАПРОСЫ • WHERE • HAVING • FROM
сервер LAST_NAME TITLE-------------- -----------Maduro Stock ClerkSmith Stock Clerk Nozaki Stock Clerk Patel Stock Clerk Newman Stock Clerk Chang Stock Clerk Patel Stock Clerk Danca Stock Clerk Schwartz Stock Clerk TITLE LAST_NAME ----------- -----------Stock Clerk Smith Подзапросы: пример
Вложенная команда SELECT выполняется первой. Результат передается в условие главного запроса. Вложенный запрос Главный запрос SELECT dept_id FROM s_emp WHERE last_name='Biri' SELECT last_name, title FROM s_emp WHERE dept_id = 43 Как обрабатываются вложенныеподзапросы?
Предложение HAVING с подзапросами • Подзапросы используются и в предложениях HAVING. • Сервер Oracle выполняет подзапросы первыми. • Сервер возвращает результаты в предложение HAVING главного запроса. SQL> SELECT dept_id, AVG(salary) 2 FROM s_emp 3 GROUP ВY dept_id 4 HAVING AVG(salary) > 5 (SELECT AVG(salary) 6 FROM s_emр 7 WHERE dept_id = 32) ;
Однострочные подзапросы • Команда SQL для вывода фамилии и должности служащего • Команда SQL дпя выяснения должности сотрудника с фамилией Smith • Соедините обе команды, и пусть SQL определит должность сотрудника с фамилией Smith. SELECT last_name,title FROM s_emp WHERE title = SELECT title FROM s_emp WHERE last_name = ‘Smith’ SQL> SELECT last_name, title 2 FROM s_emp 3 WHERE title = 4 (SELECT title 5 FROM s_emp 6 WHERE last_name = ‘Smith’);
Пример Вывод фамилии, должности и заработной платы всех сотрудников с заработной платой ниже средней. SQL> SELECT last_name, title, salary 2 FROM s_emp 3 WHERE salary < 4 (SELECT AVG (salary) 5 FROM s_emp); LAST_NAME TITLE SALARY ---------------- ----------------- ------ Urguhart Warehouse Manager 1200 Menchu Warehouse Manager 1250 Biri Warehouse Manager 1100 Smith Stock Clerk 940 Nozaki Stock Clerk 1200 Patel Stock Clerk 795 Newman Stock Clerk 750 Markarian Stock Clerk 850 Chang Stock Clerk 800 Patel Stock Clerk 795 Danes Stock Clerk 860 Schwartz Stock Clerk 1100 12 rows selected.
Многострочные подзапросы • Возвращают более одной строки • Используют многострочные операторы сравнения
Ошибки в подзапросах • Если пишется подзапрос, возвращающий более одной строки, и в нем используется однострочный оператор сравнения, выдается сообщение об ошибке. SQL> SELECT last_name, first_name, title 2 FROM e_emp 3 WHERE dept_id = 4 (SELECT ID 5 FROM s_dept 6 WHERE name = 'Finance’ 7 OR region_id = 2) ; ORA-01427:single-row subquery returns more than one row • Для исправления измените этот оператор на (многострочный оператор сравнения).
Многострочные подзапросы: пример • Вместо оператора IN используется оператор =ANY. SQL> SELECT last_name, first_name, title 2 FROM s_emp 3 WHERE dept_id= ANY 4 (SELECT ID 5 FROM s_dept 6 WHERE name = 'Finance' 7 OR region_id = 2) ;
Использование оператора ANY в многострочных подзапросах SQL> SELECT empno, ename, job 2 FROM emp 3 WHERE sal<ANY 4 (SELECT sal 5 FROM emp 6 WHERE job = ‘CLERK’) 7 AND job <> ‘CLERK’; EMPNO ENAME JOB ------- ----------- ------ 7654 MARTIN SALESMAN 7521 WARD SALASMAN
Использование оператора ALL в многострочных подзапросах SQL> SELECT empno, ename, job 2 FROM emp 3 WHERE sal>ALL 4 (SELECT avg(sal ) 5 FROM emp 6 GROUP BY deptno); EMPNO ENAME JOB ------- ----------- ------ 7839 KING PRESIDENT 7566 JONES MANAGER 7902 FORD ANALYST 7788 SCOTT ANALYST
Многостолбцовые подзапросы Главный запрос MANAGER 10 Подзапрос SALESMAN 30 MANAGER 10 CLERK 20 с значениями из многострочного и многостолбцового подзапроса Главный запрос производит сравнение MANAGER 10 SALESMAN 30 MANAGER 10 CLARK 20
Использование многостолбцовых подзапросов Вывод фамилии, номера отдела, оклада и комиссионных всех служащих, оклад и комиссионные которых совпадают как с окладом, так и с комиссионными одного и того же служащего в отделе 30. SQL> SELECT ename, deptno, sal, comm 2 FROM emp 3 WHERE (sal, NVL(comm,-1)) IN 4 (SELECT sal, NVL(comm,-1) 5 FROM emp 6 WHERE deptno = 30);
Сравнение столбцов Парное SAL COMM 1600 300 1250 500 1250 1400 2850 1500 0 950 Непарное SAL COMM 1600 300 1250 500 1250 1400 2850 1500 0 950
Подзапрос с непарным сравнением Вывод фамилии, номера отдела, оклада и комиссионных всех служащих, оклад и комиссионные которых совпадают с комиссионными и окладом любого служащего в отделе 30. SQL> SELECT ename, deptno, sal, comm 2 FROM emp 3 WHERE sal IN (SELECT sal 4 FROM emp 5 WHERE deptno = 30) 6 AND 7 NVL(comm, -1) IN (SELECT NVL(comm,-1) 8 FROM emp 9 WHERE deptno=30);
Изменения таблицы EMP • Предположим, что изменяются оклады комиссионные Кларка (Clark). • Новый оклад - до 1500 долларов, в новые комиссионные - до 300 долларов. ENAME SAL COMM ------- --------- ------ … CLARK 1500 300 … ALLEN 1600 300 TURNER 1500 0 … 14 rows selected.
Подзапросы с парным сравнением SQL> SELECT ename, deptno, sal, comm 2 FROM emp 3 WHERE (sal, NVL(comm, -1)) IN 4 (SELECT sal, NVL(comm, -1) 5 FROM emp 6 WHERE deptno = 30); ENAME DEPTNO SAL COMM ----- ------ --- ---- JAMES 30 950 WARD 30 1250 500 MARTIN 30 1250 1400 TURNER 30 1500 0 ALLEN 30 1600 300 BLAKE 30 2850 6 rows selected.
Подзапросы с непарным сравнением SQL> SELECT ename, deptno, sal, comm 2 FROM emp 3 WHERE sal IN (SELECT sal 4 FROM emp 5 WHERE deptno = 30) 6 AND 7 NVL(comm, -1) IN (SELECT NVL(comm, -1) 8 FROM emp 9 WHERE deptno = 30); ENAME DEPTNO SAL COMM ----- ------ --- ---- JAMES 30 950 BLAKE 30 2850 TURNER 30 1500 0 CLARK 30 1500 300 ... 7 rows selected.
Неопределенное значение в подзапросе SQL> SELECT employee.ename 2 FROM emp employee 3 WHERE employee.empno NOT IN 4 (SELECT manager.mgr 5 FROM emp manager); no rows selected.
Использование подзапроса в предложении FROM SQL> SELECT a.ename, a.deptno, b.salavg 2 FROM emp a, (SELECT deptno, avg(sal) salavg 3 FROM emp 4 GROUP BY deptno) b 5 WHERE a.deptno = b.deptno 6 AND a.sal > b.salavg; ENAME SAL DAPTNO SALAVG ----- ------ --- ---- KING 5000 10 2916.6667 JONES 2975 20 2175 SCOTT 3000 20 2175 ... 6 rows selected.
Коррелированные подзапросы: синтаксис • Внутренний подзапрос ссылается на внешний запрос • Выполнение начинается с внешнего запроса SELECT select_list FROM table1 t_alias1 WHERE expr operator (SELECT column_list FROM table2 t_alias2 WHERE t_alias1.column operator t_alias2.column);
Коррелированные подзапросы: пример • Внутренний подзапрос ссылается на внешний запрос • Выполнение начинается с внешнего запроса SQL> SELECT deptno, ename, sal 2 FROM emp x 3 WHERE sal > (SELECT AVG(sal) 4 FROM emp 5 WHERE x.deptno = deptno) 6 ORDER BY deptno;
Квантифицированные подзапросы • Использование операторов EXISTS и NOT EXISTS • Внешний запрос выполняется, если внутренний подзапрос возвращает хотя бы одну строку SQL> SELECT dname, deptno 2 FROM dept 3 WHERE NOT EXISTS 4 (SELECT * FROM emp 5 WHERE dept.deptno = emp.deptno);
Заключение • Подзапросы полезны для выборки данных по неизвестным значениям. • Вложенный запрос содержит более одного предложения SELECT. • Подзапросы обрабатываются первыми, после чего выполняется основной запрос по результатам подзапроса, переданным в предложение WHERE или HAVING. SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table);