第九章、子查询.sql 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #第九章、子查询
  2. #1、由一个具体的需求,引入子查询
  3. #需求:谁的工资比Abel的高?
  4. #方式一:
  5. SELECT last_name,salary
  6. FROM employees
  7. WHERE last_name = 'Abel';
  8. SELECT last_name,salary
  9. FROM employees
  10. WHERE salary > 11000;
  11. #方式二:自连接
  12. SELECT e2.last_name,e2.salary
  13. FROM employees e1,employees e2
  14. WHERE e2.salary > e1.salary #多表的连接条件
  15. AND e1.last_name = 'Abel';
  16. #方式三:子查询
  17. SELECT last_name,salary
  18. FROM employees
  19. WHERE salary > (
  20. SELECT salary
  21. FROM employees
  22. WHERE last_name = 'Abel'
  23. );
  24. #2、称谓的规范:外查询(或主查询)、内查询(或子查询)
  25. /*
  26. 子查询(内查询)在主查询之前一次执行完成。
  27. 子查询的结果被主查询(外查询)使用。
  28. 注意事项:
  29. 子查询要包含在括号内
  30. 将子查询放在比较条件的右侧
  31. 单行操作符对应单行子查询,多行操作符对应多行子查询
  32. */
  33. /*
  34. 3、子查询的分类
  35. 角度1:从内查询返回的结果的条目数
  36. 单行子查询 vs 多行子查询
  37. 角度2:内查询是否被执行多次
  38. 相关子查询 VS 不相关子查询
  39. 比如:相关子查询的需求:查询工资大于本部门平均工资的员工信息
  40. 不相关子查询的需求:查询工资大于本公司平均工资的员工信息
  41. */
  42. #子查询的编写技巧(或步骤):(1)、从里往外写 (2)、从外往里写
  43. #4、单行子查询
  44. #4.1、单行操作符: = != > >= < <=
  45. #题目1:查询工资大于149号员工工资的员工信息
  46. SELECT employee_id,last_name,salary
  47. FROM employees
  48. WHERE salary > (
  49. SELECT salary
  50. FROM employees
  51. WHERE employee_id = 149
  52. );
  53. #题目2:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
  54. SELECT last_name,job_id,salary
  55. FROM employees
  56. WHERE job_id = (
  57. SELECT job_id
  58. FROM employees
  59. WHERE employee_id = 141
  60. )
  61. AND salary > (
  62. SELECT salary
  63. FROM employees
  64. WHERE employee_id = 143
  65. );
  66. #题目3:返回公司工资最少的员工的last_name,job_id和salary。
  67. SELECT last_name,job_id,salary
  68. FROM employees
  69. WHERE salary = (
  70. SELECT MIN(salary)
  71. FROM employees
  72. );
  73. #题目4:查询与141号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id。
  74. #方式一:适用性更好
  75. SELECT employee_id,manager_id,department_id
  76. FROM employees
  77. WHERE manager_id = (
  78. SELECT manager_id
  79. FROM employees
  80. WHERE employee_id = 141
  81. )
  82. AND department_id = (
  83. SELECT department_id
  84. FROM employees
  85. WHERE employee_id = 141
  86. )
  87. AND employee_id <> 141;
  88. #方式二
  89. SELECT employee_id,manager_id,department_id
  90. FROM employees
  91. WHERE (manager_id,department_id)=(
  92. SELECT manager_id,department_id
  93. FROM employees
  94. WHERE employee_id = 141
  95. )
  96. AND employee_id <> 141;
  97. #题目5:查询最低工资大于110号部门最低工资的部门id和其最低工资
  98. SELECT department_id,MIN(salary)
  99. FROM employees
  100. WHERE department_id IS NOT NULL
  101. GROUP BY department_id
  102. HAVING MIN(salary) > (
  103. SELECT MIN(salary)
  104. FROM employees
  105. WHERE department_id = 110
  106. );
  107. #题目6:显示员工的employee_id,last_name和location。其中,若员工department_id与location_id为1800的department_id相同,则location为“Canada”,其余则为“USA”
  108. SELECT employee_id,last_name,
  109. CASE department_id WHEN (
  110. SELECT department_id
  111. FROM departments
  112. WHERE location_id = 1800
  113. ) THEN 'Canada'
  114. ELSE 'USA' END "location"
  115. FROM employees;
  116. #4.2、子查询中的空值问题
  117. SELECT last_name,job_id
  118. FROM employees
  119. WHERE job_id = (
  120. SELECT job_id
  121. FROM employees
  122. WHERE last_name = 'Haas'
  123. );
  124. #4.3、非法使用子查询
  125. #错误:Subquery returns more than 1 row
  126. -- SELECT employee_id,last_name
  127. -- FROM employees
  128. -- WHERE salary = (
  129. -- SELECT MIN(salary)
  130. -- FROM employees
  131. -- GROUP BY department_id
  132. -- );
  133. #5、多行子查询
  134. #5.1、多行子查询的操作符:IN ANY ALL SOME(同ANY)
  135. #5.2、举例
  136. # IN
  137. SELECT employee_id,last_name
  138. FROM employees
  139. WHERE salary IN (
  140. SELECT MIN(salary)
  141. FROM employees
  142. GROUP BY department_id
  143. );
  144. # ANY / ALL
  145. #题目:返回其他job_id中比job_id为IT_PROG部门任一工资低的员工的员工号、姓名、
  146. #job_id以及salary
  147. SELECT employee_id,last_name,job_id,salary
  148. FROM employees
  149. WHERE job_id <> 'IT_PROG'
  150. AND salary < ANY(
  151. SELECT salary
  152. FROM employees
  153. WHERE job_id = 'IT_PROG'
  154. );
  155. #题目:返回其他job_id中比job_id为IT_PROG部门所有工资低的员工的员工号、姓名、
  156. #job_id以及salary
  157. SELECT employee_id,last_name,job_id,salary
  158. FROM employees
  159. WHERE job_id <> 'IT_PROG'
  160. AND salary < ALL (
  161. SELECT salary
  162. FROM employees
  163. WHERE job_id = 'IT_PROG'
  164. );
  165. #题目:查询平均工资最低的部门id
  166. #MySQL中聚合函数是不能嵌套的
  167. #方式一:
  168. SELECT department_id
  169. FROM employees
  170. GROUP BY department_id
  171. HAVING AVG(salary) = (
  172. SELECT MIN(avg_sal)
  173. FROM (
  174. SELECT AVG(salary) avg_sal
  175. FROM employees
  176. GROUP BY department_id
  177. ) t_dept_avg_sal
  178. );
  179. #方式二:
  180. SELECT department_id
  181. FROM employees
  182. GROUP BY department_id
  183. HAVING AVG(salary) <= ALL (
  184. SELECT AVG(salary) avg_sal
  185. FROM employees
  186. GROUP BY department_id
  187. );
  188. #5.3、空值问题
  189. SELECT last_name
  190. FROM employees
  191. WHERE employee_id NOT IN (
  192. SELECT manager_id
  193. FROM employees
  194. WHERE manager_id IS NOT NULL
  195. );
  196. #6、相关子查询
  197. #6.1
  198. #回顾:查询员工中工资大于公司平均工资的员工的last_name,salary和其department_id
  199. SELECT last_name,salary,department_id
  200. FROM employees
  201. WHERE salary > (
  202. SELECT AVG(salary)
  203. FROM employees
  204. );
  205. #题目2:查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id
  206. #方式一:使用相关子查询
  207. SELECT last_name,salary,department_id
  208. FROM employees e1
  209. WHERE salary > (
  210. SELECT AVG(salary)
  211. FROM employees e2
  212. WHERE department_id = e1.department_id
  213. );
  214. #方式二:在FROM中声明子查询
  215. SELECT e.last_name,e.salary,e.department_id
  216. FROM employees e,(
  217. SELECT department_id,AVG(salary) avg_sal
  218. FROM employees
  219. GROUP BY department_id
  220. ) t_dept_avg_sal
  221. WHERE e.department_id = t_dept_avg_sal.department_id
  222. AND e.salary > t_dept_avg_sal.avg_sal;
  223. #题目:查询员工的id,salary,按照department_name排序
  224. SELECT employee_id,salary
  225. FROM employees e
  226. ORDER BY (
  227. SELECT department_name
  228. FROM departments d
  229. WHERE e.department_id = d.department_id
  230. ) ASC;
  231. #结论:在SELECT中,除了GROUP BY和LIMIT之外,其他位置都可以声明子查询。
  232. #题目:若employees表中employee_id与job_history表中employee_id相同的数目
  233. #不小于2,输出这些相同id的员工的employee_id,last_name和job_id。
  234. SELECT * FROM job_history;
  235. SELECT employee_id,last_name,job_id
  236. FROM employees e
  237. WHERE 2 <=(
  238. SELECT COUNT(*)
  239. FROM job_history j
  240. WHERE e.employee_id = j.employee_id
  241. );
  242. #6.2、EXISTS与NOT EXISTS关键字
  243. #题目:查询公司管理者的employee_id,last_name,job_id,department_id信息
  244. #方式一:自连接
  245. SELECT DISTINCT mgr.employee_id,mgr.last_name,mgr.job_id,mgr.department_id
  246. FROM employees emp JOIN employees mgr
  247. ON emp.manager_id = mgr.employee_id;
  248. #方式二:子查询
  249. SELECT DISTINCT employee_id,last_name,job_id,department_id
  250. FROM employees emp
  251. WHERE employee_id IN (
  252. SELECT DISTINCT manager_id
  253. FROM employees
  254. );
  255. #我做的
  256. SELECT employee_id,last_name,job_id,department_id
  257. FROM employees
  258. WHERE employee_id IN (
  259. SELECT manager_id
  260. FROM employees
  261. WHERE manager_id IS NOT NULL
  262. GROUP BY manager_id
  263. );
  264. #方式三:EXISTS
  265. SELECT employee_id,last_name,job_id,department_id
  266. FROM employees e1
  267. WHERE EXISTS (
  268. SELECT *
  269. FROM employees e2
  270. WHERE e1.employee_id = e2.manager_id
  271. );
  272. #题目:查询departments表中,不存在与employees表中的部门的department_id和department_name。
  273. #方式一:外连接
  274. SELECT d.department_id,d.department_name
  275. FROM employees e RIGHT JOIN departments d
  276. ON e.department_id = d.department_id
  277. WHERE e.department_id IS NULL;
  278. #方式二:使用NOT EXISTS
  279. SELECT department_id,department_name
  280. FROM departments d
  281. WHERE NOT EXISTS (
  282. SELECT *
  283. FROM employees e
  284. WHERE d.department_id = e.department_id
  285. );