[Oracle数据库学习]十八、高级子查询
D12
子查询
子查询是嵌套在SQL语句中的另一个SELECT语句。
SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table);
子查询在主查询之前进行,结果共主查询使用。
示例:
SELECT last_name FROM hr.employees WHERE salary > (SELECT salary FROM hr.employees WHERE employee_id = 149) ;
| LAST_NAME |
|---|
| King |
| Kochhar |
| De Haan |
| Greenberg |
| Raphaely |
| Russell |
| Partners |
| Errazuriz |
| Cambrault |
| Ozer |
| Abel |
| Hartstein |
| Higgins |
13 rows selected.
多列子查询
子查询返回多列,主查询与子查询返回的多个列进行比较。
多列子查询中的比较分为两种:
1)成对比较
2)不成对比较
成对比较
SELECT employee_id, manager_id, department_id FROM hr.employees WHERE (manager_id, department_id) IN (SELECT manager_id, department_id FROM hr.employees WHERE employee_id IN (178,174)) AND employee_id NOT IN (178,174);
| EMPLOYEE_ID | MANAGER_ID | DEPARTMENT_ID |
|---|---|---|
| 175 | 149 | 80 |
| 176 | 149 | 80 |
| 177 | 149 | 80 |
| 179 | 149 | 80 |
4 rows selected.
不成对比较
SELECT employee_id, manager_id, department_id FROM hr.employees WHERE manager_id IN (SELECT manager_id FROM hr.employees WHERE employee_id IN (174,141)) AND department_id IN (SELECT department_id FROM hr.employees WHERE employee_id IN (174,141)) AND employee_id NOT IN (174,141);
| EMPLOYEE_ID | MANAGER_ID | DEPARTMENT_ID |
|---|---|---|
| 142 | 124 | 50 |
| 143 | 124 | 50 |
| 144 | 124 | 50 |
| 196 | 124 | 50 |
| 197 | 124 | 50 |
| 198 | 124 | 50 |
| 199 | 124 | 50 |
| 175 | 149 | 80 |
| 176 | 149 | 80 |
| 177 | 149 | 80 |
| 179 | 149 | 80 |
11 rows selected.
在FROM子句中使用子查询
SELECT a.last_name, a.salary, a.department_id, b.salavg FROM hr.employees a, (SELECT department_id, AVG(salary) salavg FROM hr.employees GROUP BY department_id) b WHERE a.department_id = b.department_id AND a.salary > b.salavg;
| LAST_NAME | SALARY | DEPARTMENT_ID | SALAVG |
|---|---|---|---|
| King | 24000 | 90 | 19333.3333333333333333333333333333333333 |
| Hunold | 9000 | 60 | 5760 |
| Ernst | 6000 | 60 | 5760 |
| Greenberg | 12008 | 100 | 8601.333333333333333333333333333333333333 |
| Faviet | 9000 | 100 | 8601.333333333333333333333333333333333333 |
| Raphaely | 11000 | 30 | 4150 |
| Weiss | 8000 | 50 | 3475.555555555555555555555555555555555556 |
| Fripp | 8200 | 50 | 3475.555555555555555555555555555555555556 |
| Kaufling | 7900 | 50 | 3475.555555555555555555555555555555555556 |
| Vollman | 6500 | 50 | 3475.555555555555555555555555555555555556 |
| Mourgos | 5800 | 50 | 3475.555555555555555555555555555555555556 |
| Ladwig | 3600 | 50 | 3475.555555555555555555555555555555555556 |
| Rajs | 3500 | 50 | 3475.555555555555555555555555555555555556 |
| Russell | 14000 | 80 | 8955.882352941176470588235294117647058824 |
| Partners | 13500 | 80 | 8955.882352941176470588235294117647058824 |
| Errazuriz | 12000 | 80 | 8955.882352941176470588235294117647058824 |
| Cambrault | 11000 | 80 | 8955.882352941176470588235294117647058824 |
| Zlotkey | 10500 | 80 | 8955.882352941176470588235294117647058824 |
| Tucker | 10000 | 80 | 8955.882352941176470588235294117647058824 |
| Bernstein | 9500 | 80 | 8955.882352941176470588235294117647058824 |
| Hall | 9000 | 80 | 8955.882352941176470588235294117647058824 |
| King | 10000 | 80 | 8955.882352941176470588235294117647058824 |
| Sully | 9500 | 80 | 8955.882352941176470588235294117647058824 |
| McEwen | 9000 | 80 | 8955.882352941176470588235294117647058824 |
| Vishney | 10500 | 80 | 8955.882352941176470588235294117647058824 |
| Greene | 9500 | 80 | 8955.882352941176470588235294117647058824 |
| Ozer | 11500 | 80 | 8955.882352941176470588235294117647058824 |
| Bloom | 10000 | 80 | 8955.882352941176470588235294117647058824 |
| Fox | 9600 | 80 | 8955.882352941176470588235294117647058824 |
| Abel | 11000 | 80 | 8955.882352941176470588235294117647058824 |
| Sarchand | 4200 | 50 | 3475.555555555555555555555555555555555556 |
| Bull | 4100 | 50 | 3475.555555555555555555555555555555555556 |
| Chung | 3800 | 50 | 3475.555555555555555555555555555555555556 |
| Dilly | 3600 | 50 | 3475.555555555555555555555555555555555556 |
| Bell | 4000 | 50 | 3475.555555555555555555555555555555555556 |
| Everett | 3900 | 50 | 3475.555555555555555555555555555555555556 |
| Hartstein | 13000 | 20 | 9500 |
| Higgins | 12008 | 110 | 10154 |
38 rows selected.
单列子查询表达式
单列子查询表达式是在一行中只返回一列的子查询。
Oracle8i只在下列情况下可以使用, 例如:
–SELECT语句(FROM和WHERE子句)
–INSERT语句中的VALUES列表中
Oracle9i中单列子查询表达式可在下列情况下使用:
–DECODE和CASE
–SELECT中除GROUP BY子句以外的所有子句中
在CASE语句中使用子查询
先看一下子查询的结果是单行单列:
SELECT department_id FROM hr.departments WHERE location_id = 1500;
| DEPARTMENT_ID |
|---|
| 50 |
示例:
SELECT employee_id, last_name, (CASE WHEN department_id = (SELECT department_id FROM hr.departments WHERE location_id = 1500) THEN 'Canada' ELSE 'USA' END) location FROM hr.employees;
| EMPLOYEE_ID | LAST_NAME | LOCATION |
|---|---|---|
| 100 | King | USA |
| 101 | Kochhar | USA |
| 102 | De Haan | USA |
| 103 | Hunold | USA |
| 104 | Ernst | USA |
| 105 | Austin | USA |
| 106 | Pataballa | USA |
| 107 | Lorentz | USA |
| 108 | Greenberg | USA |
| 109 | Faviet | USA |
| 110 | Chen | USA |
| 111 | Sciarra | USA |
| 112 | Urman | USA |
| 113 | Popp | USA |
| 114 | Raphaely | USA |
| 115 | Khoo | USA |
| 116 | Baida | USA |
| 117 | Tobias | USA |
| 118 | Himuro | USA |
| 119 | Colmenares | USA |
| 120 | Weiss | Canada |
| 121 | Fripp | Canada |
| 122 | Kaufling | Canada |
| 123 | Vollman | Canada |
| 124 | Mourgos | Canada |
| 125 | Nayer | Canada |
| 126 | Mikkilineni | Canada |
| 127 | Landry | Canada |
| 128 | Markle | Canada |
| 129 | Bissot | Canada |
| 130 | Atkinson | Canada |
| 131 | Marlow | Canada |
| 132 | Olson | Canada |
| 133 | Mallin | Canada |
| 134 | Rogers | Canada |
| 135 | Gee | Canada |
| 136 | Philtanker | Canada |
| 137 | Ladwig | Canada |
| 138 | Stiles | Canada |
| 139 | Seo | Canada |
| 140 | Patel | Canada |
| 141 | Rajs | Canada |
| 142 | Davies | Canada |
| 143 | Matos | Canada |
| 144 | Vargas | Canada |
| 145 | Russell | USA |
| 146 | Partners | USA |
| 147 | Errazuriz | USA |
| 148 | Cambrault | USA |
| 149 | Zlotkey | USA |
Rows 1 - 50. More rows exist.
在Order By子句中使用单列子查询
SELECT employee_id, last_name FROM hr.employees e ORDER BY (SELECT department_name FROM hr.departments d WHERE e.department_id = d.department_id);
| EMPLOYEE_ID | LAST_NAME |
|---|---|
| 205 | Higgins |
| 206 | Gietz |
| 200 | Whalen |
| 100 | King |
| 101 | Kochhar |
| 102 | De Haan |
| 109 | Faviet |
| 108 | Greenberg |
| 112 | Urman |
| 111 | Sciarra |
| 110 | Chen |
| 113 | Popp |
| 203 | Mavris |
| 107 | Lorentz |
| 106 | Pataballa |
| 105 | Austin |
| 103 | Hunold |
| 104 | Ernst |
| 201 | Hartstein |
| 202 | Fay |
| 204 | Baer |
| 119 | Colmenares |
| 114 | Raphaely |
| 115 | Khoo |
| 116 | Baida |
| 117 | Tobias |
| 118 | Himuro |
| 167 | Banda |
| 168 | Ozer |
| 169 | Bloom |
| 170 | Fox |
| 171 | Smith |
| 172 | Bates |
| 173 | Kumar |
| 174 | Abel |
| 175 | Hutton |
| 176 | Taylor |
| 177 | Livingston |
| 179 | Johnson |
| 145 | Russell |
| 146 | Partners |
| 147 | Errazuriz |
| 148 | Cambrault |
| 149 | Zlotkey |
| 150 | Tucker |
| 151 | Bernstein |
| 152 | Hall |
| 153 | Olsen |
| 154 | Cambrault |
| 155 | Tuvault |
Rows 1 - 50. More rows exist.
相关子查询
相关子查询按照一行接一行的顺序执行,主查询的每一行都执行一次子查询。
GET:从主查询中获取候选列
EXECUTE:子查询使用主查询的数据:
USE:如果满足内查询的条件则返回该行
D13
子查询使用主查询中的列。
SELECT column1, column2, ... FROM table1 outer WHERE column1 operator (SELECT colum1, column2 FROM table2 WHERE expr1= outer.expr2);
示例:
SELECT last_name, salary, department_id FROM hr.employees outer WHERE salary > (SELECT AVG(salary) FROM hr.employees WHERE department_id = outer.department_id) ;
| LAST_NAME | SALARY | DEPARTMENT_ID |
|---|---|---|
| King | 24000 | 90 |
| Hunold | 9000 | 60 |
| Ernst | 6000 | 60 |
| Greenberg | 12008 | 100 |
| Faviet | 9000 | 100 |
| Raphaely | 11000 | 30 |
| Weiss | 8000 | 50 |
| Fripp | 8200 | 50 |
| Kaufling | 7900 | 50 |
| Vollman | 6500 | 50 |
| Mourgos | 5800 | 50 |
| Ladwig | 3600 | 50 |
| Rajs | 3500 | 50 |
| Russell | 14000 | 80 |
| Partners | 13500 | 80 |
| Errazuriz | 12000 | 80 |
| Cambrault | 11000 | 80 |
| Zlotkey | 10500 | 80 |
| Tucker | 10000 | 80 |
| Bernstein | 9500 | 80 |
| Hall | 9000 | 80 |
| King | 10000 | 80 |
| Sully | 9500 | 80 |
| McEwen | 9000 | 80 |
| Vishney | 10500 | 80 |
| Greene | 9500 | 80 |
| Ozer | 11500 | 80 |
| Bloom | 10000 | 80 |
| Fox | 9600 | 80 |
| Abel | 11000 | 80 |
| Sarchand | 4200 | 50 |
| Bull | 4100 | 50 |
| Chung | 3800 | 50 |
| Dilly | 3600 | 50 |
| Bell | 4000 | 50 |
| Everett | 3900 | 50 |
| Hartstein | 13000 | 20 |
| Higgins | 12008 | 110 |
38 rows selected.
注:主查询的每一行,需要进行子查询后才能判断是否输出。
示例2:
SELECT e.employee_id, last_name, e.job_id FROM hr.employees e WHERE 2 <= (SELECT COUNT(*) FROM hr.job_history WHERE employee_id = e.employee_id);
| EMPLOYEE_ID | LAST_NAME | JOB_ID |
|---|---|---|
| 101 | Kochhar | AD_VP |
| 176 | Taylor | SA_REP |
| 200 | Whalen | AD_ASST |
3 rows selected.
注:主查询的每一行取出的employee_id,在子查询中使用得到结果,比较后确定是否输出。
EXISTS操作符
EXISTS 操作符检查在子查询中是否存在满足条件的行
如果在子查询中存在满足条件的行:
–不在子查询中继续查找
–条件返回TRUE
如果在子查询中不存在满足条件的行:
–条件返回FALSE
–继续在子查询中查找
示例:
SELECT employee_id, last_name, job_id, department_id FROM hr.employees outer WHERE EXISTS ( SELECT 'X' FROM hr.employees WHERE manager_id = outer.employee_id);
| EMPLOYEE_ID | LAST_NAME | JOB_ID | DEPARTMENT_ID |
|---|---|---|---|
| 100 | King | AD_PRES | 90 |
| 101 | Kochhar | AD_VP | 90 |
| 102 | De Haan | AD_VP | 90 |
| 103 | Hunold | IT_PROG | 60 |
| 108 | Greenberg | FI_MGR | 100 |
| 114 | Raphaely | PU_MAN | 30 |
| 120 | Weiss | ST_MAN | 50 |
| 121 | Fripp | ST_MAN | 50 |
| 122 | Kaufling | ST_MAN | 50 |
| 123 | Vollman | ST_MAN | 50 |
| 124 | Mourgos | ST_MAN | 50 |
| 145 | Russell | SA_MAN | 80 |
| 146 | Partners | SA_MAN | 80 |
| 147 | Errazuriz | SA_MAN | 80 |
| 148 | Cambrault | SA_MAN | 80 |
| 149 | Zlotkey | SA_MAN | 80 |
| 201 | Hartstein | MK_MAN | 20 |
| 205 | Higgins | AC_MGR | 110 |
18 rows selected.
NOT EXISTS 操作符
示例:
SELECT department_id, department_name FROM hr.departments d WHERE NOT EXISTS (SELECT 'X' FROM hr.employees WHERE department_id = d.department_id);
| DEPARTMENT_ID | DEPARTMENT_NAME |
|---|---|
| 120 | Treasury |
| 130 | Corporate Tax |
| 140 | Control And Credit |
| 150 | Shareholder Services |
| 160 | Benefits |
| 170 | Manufacturing |
| 180 | Construction |
| 190 | Contracting |
| 200 | Operations |
| 210 | IT Support |
| 220 | NOC |
| 230 | IT Helpdesk |
| 240 | Government Sales |
| 250 | Retail Sales |
| 260 | Recruiting |
| 270 | Payroll |
16 rows selected.
注:查询结果为没有在employee中出现的department。
相关更新
使用相关子查询依据一个表中的数据更新另一个表的数据。
UPDATE table1 alias1 SET column = (SELECT expression FROM table2 alias2 WHERE alias1.column = alias2.column);
示例:
ALTER TABLE employees ADD (department_name VARCHAR2(14));
注:增加列。
UPDATE employees e SET department_name = (SELECT department_name FROM departments d WHERE e.department_id = d.department_id);
注:新增的列赋值:使用子查询。
相关删除
使用相关子查询依据一个表中的数据删除另一个表的数据。
DELETE FROM table1 alias1 WHERE column operator (SELECT expression FROM table2 alias2 WHERE alias1.column = alias2.column);
示例:
DELETE FROM employees e WHERE employee_id = (SELECT employee_id FROM emp_history WHERE employee_id = e.employee_id);
WITH子句
使用WITH子句, 可以避免在SELECT语句中重复书写相同的语句块,可以提高查询效率
WITH子句将该子句中的语句块执行一次并存储到用户的临时表空间中。
示例:
WITH dept_costs AS (SELECT d.department_name, SUM(e.salary) AS dept_total FROM employees e, departments d WHERE e.department_id = d.department_id GROUP BY d.department_name), avg_cost AS (SELECT SUM(dept_total)/COUNT(*) AS dept_avg FROM dept_costs) SELECT * FROM dept_costs WHERE dept_total >(SELECT dept_avg FROM avg_cost) ORDER BY department_name;
| DEPARTMENT_NAME | DEPT_TOTAL |
|---|---|
| Sales | 304500 |
| Shipping | 156400 |
2 rows selected.
总结:
本节介绍高级子查询内容:
1)多列子查询:主查询的列成对/不成对与子查询的列比较;
2)单列子查询:可以在DECODE/CASE等语句使用;
3)相关子查询:主查询的每一行都执行一次子查询;
4)EXISTS和NOT EXISTS关键字:判断子查询是否存在满足条件的行;
5)相关更新和相关删除:使用相关子查询,依据一个表中的数据更新/删除另一个表的数据;
6)WITH子句:执行语句块并将结果存入用户的临时空间,避免重复执行语句块。

浙公网安备 33010602011771号