1 #进阶7:子查询
2 /*
3 含义:
4 出现在其他语句中的select语句,称为子查询或内查询
5 外部的查询语句,称为主查询或外查询
6
7 分类:
8 按子查询出现的位置:
9 select后面:
10 仅仅支持标量子查询
11 from后面:
12 支持表子查询
13 where或having后面:(√)
14 标量子查询(√)
15 列子查询 (√)
16 行子查询
17 exists后面(相关子查询):
18 表子查询
19 按结果集的行列数不同:
20 标量子查询(结果集只有一行一列)
21 列子查询(结果集有多行一列)
22 行子查询(结果集有一行多列)
23 表子查询(结果集一般为多行多列)
24 */
25
26 #一、where或having后面
27 /*
28 1.标量子查询(单行子查询)
29 2.列子查询(多行子查询)
30 3.行子查询(多列多行)
31
32 特点:
33 (1)子查询放在小括号内
34 (2)子查询一般放在条件的右侧
35 (3)标量子查询,一般搭配着单行操作符使用
36 > < >= <= <>
37
38 列子查询,一般搭配着多行操作符使用
39 in、any/some、all
40 (4)子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
41 */
42
43 #1.标量子查询
44 #案例1:谁的工资比Abel高?
45 #(1)查询Abel的工资
46 SELECT salary
47 FROM employees
48 WHERE last_name='Abel';
49 #(2)查询员工的信息,满足salary>(1)的结果
50 SELECT *
51 FROM employees
52 WHERE salary>(
53 SELECT salary
54 FROM employees
55 WHERE last_name='Abel'
56 );
57 #案例2:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
58 #(1)查询141号员工的job_id
59 SELECT job_id
60 FROM employees
61 WHERE employee_id='141'
62 #(2)查询143号员工的salary
63 SELECT salary
64 FROM employees
65 WHERE employee_id='143'
66 #(3)查询员工姓名,job_id和工资,要求job_id=(1)并且salary>(2)
67 SELECT last_name,job_id,salary
68 FROM employees WHERE job_id=(
69 SELECT job_id
70 FROM employees
71 WHERE employee_id='141'
72 )AND salary>(
73 SELECT salary
74 FROM employees
75 WHERE employee_id='143'
76 );
77 #案例3:返回公司工资最少的员工的last_name,job_id和salary
78 #(1)查询公司的最低工资
79 SELECT MIN(salary)
80 FROM employees
81 #(2)查询last_name,job_id和salary,要求salary=(1)
82 SELECT last_name,job_id,salary
83 FROM employees
84 WHERE salary=(
85 SELECT MIN(salary)
86 FROM employees
87 );
88 #案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
89 #(1)查询50号部门的最低工资
90 SELECT MIN(salary)
91 FROM employees
92 WHERE department_id='50'
93 #(2)查询每个部门的最低工资
94 SELECT department_id,MIN(salary) '最低工资'
95 FROM employees
96 GROUP BY department_id
97 #(3)在(2)的基础上筛选,满足min(salary)>(1)
98 SELECT department_id,MIN(salary) '最低工资'
99 FROM employees
100 GROUP BY department_id
101 HAVING 最低工资>(
102 SELECT MIN(salary)
103 FROM employees
104 WHERE department_id='50'
105 );
106
107 #非法使用标量子查询——子查询的结果不是一行一列
108 SELECT department_id,MIN(salary) '最低工资'
109 FROM employees
110 GROUP BY department_id
111 HAVING 最低工资>(
112 SELECT salary
113 FROM employees
114 WHERE department_id='50'
115 );
116
117
118 #2.列子查询(多行子查询)
119 #案例1:返回location_id是1400或1700的部门中的所有员工姓名
120 #(1)查询location_id是1400或1700的部门编号
121 SELECT DISTINCT department_id
122 FROM departments
123 WHERE location_id IN(1400,1700)
124 #(2)查询员工姓名,要求部门号是(1)列表中的某一个
125 SELECT last_name
126 FROM employees
127 WHERE department_id IN(
128 SELECT DISTINCT department_id
129 FROM departments
130 WHERE location_id IN(1400,1700)
131 );
132 #或
133 SELECT last_name
134 FROM employees
135 WHERE department_id =ANY(
136 SELECT DISTINCT department_id
137 FROM departments
138 WHERE location_id IN(1400,1700)
139 );
140 #案例2:返回其他工种中比job_id为'IT_PROG'工种任一工资低的员工的
141 #员工号、姓名、job_id以及salary
142 #(1)查询job_id为'IT_PROG'工种任一工资
143 SELECT salary
144 FROM employees
145 WHERE job_id='IT_PROG'
146 #(2)查询员工号、姓名、job_id以及salary,salary<(1)中的任意一个
147 SELECT employee_id,last_name,job_id,salary
148 FROM employees
149 WHERE salary<ANY(
150 SELECT salary
151 FROM employees
152 WHERE job_id='IT_PROG'
153 )AND job_id <>'IT_PROG';
154 #或
155 SELECT employee_id,last_name,job_id,salary
156 FROM employees
157 WHERE salary<(
158 SELECT MAX(salary)
159 FROM employees
160 WHERE job_id='IT_PROG'
161 )AND job_id <>'IT_PROG';
162 #案例3:返回其他工种中比job_id为'IT_PROG'工种所有工资都低的员工的
163 #员工号、姓名、job_id以及salary
164 SELECT employee_id,last_name,job_id,salary
165 FROM employees
166 WHERE salary<ALL(
167 SELECT DISTINCT salary
168 FROM employees
169 WHERE job_id='IT_PROG'
170 )AND job_id <>'IT_PROG';
171 #或
172 SELECT employee_id,last_name,job_id,salary
173 FROM employees
174 WHERE salary<(
175 SELECT DISTINCT MIN(salary)
176 FROM employees
177 WHERE job_id='IT_PROG'
178 )AND job_id <>'IT_PROG';
179
180 #3.行子查询(结果集一行多列或多行多列)
181 #案例:查询员工编号最小并且工资最高的员工信息
182 #(1)查询最小的员工编号
183 SELECT MIN(employee_id)
184 FROM employees
185 #(2)查询最高工资
186 SELECT MAX(salary)
187 FROM employees
188 #(3)查询员工信息
189 SELECT * FROM employees
190 WHERE employee_id=(
191 SELECT MIN(employee_id)
192 FROM employees
193 ) AND salary=(
194 SELECT MAX(salary)
195 FROM employees
196 );
197 #或
198 SELECT * FROM employees
199 WHERE (employee_id,salary)=(
200 SELECT MIN(employee_id),MAX(salary)
201 FROM employees
202 );
203
204 #二、select后面
205 /*
206 仅仅支持标量子查询
207 */
208 #案例:查询每个部门的员工个数
209 SELECT d.*,(
210 SELECT COUNT(*)
211 FROM employees e
212 WHERE e.department_id=d.department_id
213 ) 个数
214 FROM departments d;
215 #案例2:查询员工号=102的部门名
216 SELECT(
217 SELECT department_name
218 FROM departments d
219 INNER JOIN employees e ON d.department_id=e.department_id
220 WHERE e.employee_id='102'
221 ) 部门名;
222
223 #三、from后面
224 /*
225 将子查询结果充当一张表,要求必须起别名
226 */
227 #案例:查询每个部门的平均工资的工资等级
228 #(1)查询每个部门的平均工资
229 SELECT AVG(salary),department_id
230 FROM employees
231 GROUP BY department_id
232 #(2)连接(1)的结果集和job_grades表,筛选条件平均工资
233 SELECT ag_dep.*,grade_level
234 FROM (
235 SELECT AVG(salary) ag,department_id
236 FROM employees
237 GROUP BY department_id
238 ) ag_dep
239 INNER JOIN job_grades ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;
240
241 #四、exists后面(相关子查询)
242 /*
243 语法:
244 exists(完整的查询语句)
245 结果:
246 1或0
247 */
248 SELECT EXISTS(SELECT employee_id FROM employees WHERE salary='30000');
249 #案例1:查询有员工的部门名
250 #in
251 SELECT department_name FROM departments
252 WHERE department_id IN(
253 SELECT department_id FROM employees
254 WHERE employee_id IS NOT NULL
255 );
256 #exists
257 SELECT department_name FROM departments d
258 WHERE EXISTS (
259 SELECT employee_id FROM employees e
260 WHERE d.department_id=e.department_id
261 );
262
263 #案例2:查询没有女朋友的男神信息
264 #in
265 SELECT * FROM boys
266 WHERE boys.id NOT IN (
267 SELECT boyfriend_id FROM beauty
268 );
269 #exists
270 SELECT * FROM boys bo
271 WHERE NOT EXISTS(
272 SELECT boyfriend_id FROM beauty b
273 WHERE bo.id=b.boyfriend_id
274 );