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 );