[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子句:执行语句块并将结果存入用户的临时空间,避免重复执行语句块。