含义:出现在其他语句内部的 SELECT 语句,称为子查询或内查询。内部嵌套了其他 SELECT 语句的查询,称为外查询或主查询。

特点

  • 子查询放在小括号内。
  • 子查询一般放在条件的右侧。
  • 子查询的执行优于主查询执行,主查询的条件用到了子查询的结果。


分类

出现位置分类

位置 支持情况
SELECT 后面 标量子查询
FROM 后面 表子查询
WHERE 或 HAVING 后面 标量子查询/列子查询/行子查询(比较少用)
EXISTS 后面 表子查询

结果集行列数分类

类型 结果集
标量子查询 一行一列
列子查询 一列多行
行子查询 一行多列
表子查询 多行多列

案例

WHERE 或 HAVING 后面

标量子查询

  1. -- 谁的工资币 Abel 高。
  2. SELECT
  3. *
  4. FROM
  5. employees
  6. WHERE
  7. salary > ( SELECT salary FROM employees WHERE last_name = 'Abel' );
  8. -- 返回job_id 141 号员工相同,salary 143 号员工多的员工 姓名、job_id 工资。
  9. SELECT
  10. last_name,
  11. job_id,
  12. salary
  13. FROM
  14. employees
  15. WHERE
  16. job_id = ( SELECT job_id FROM employees WHERE employee_id = 141 )
  17. AND salary > ( SELECT salary FROM employees WHERE employee_id = 143 );
  18. -- 返回公司工资最少的员工的 last_namejob_idsalary
  19. SELECT last_name, job_id, salary FROM employees WHERE salary =( SELECT MIN( salary ) FROM employees );
  20. -- 查询最低工资 > 50 号部门最低工资的部门和其最低工资。
  21. SELECT
  22. MIN( salary ),
  23. department_id
  24. FROM
  25. employees
  26. GROUP BY
  27. department_id
  28. HAVING
  29. MIN( salary ) > ( SELECT MIN( salary ) FROM employees WHERE department_id = 50 );

列子查询

一般会使用到几个关键字。

关键字 含义
IN/NOT IN 等于列表中的任意一个
ANY/SOME 和子查询返回的某一个值比较
ALL 和子查询返回的所有值比较
  1. -- 返回 location_id 1400 1700 的部门中的所有员工姓名。
  2. SELECT
  3. last_name
  4. FROM
  5. employees
  6. WHERE
  7. department_id IN ( SELECT DISTINCT department_id FROM departments WHERE location_id IN ( 1400, 1700 ) );
  8. SELECT
  9. last_name
  10. FROM
  11. employees
  12. WHERE
  13. department_id = any( SELECT DISTINCT department_id FROM departments WHERE location_id IN ( 1400, 1700 ) );
  14. -- 返回其他工种中比 job_id IT_PROG 任一工资低的员工名、姓名、job_idsalary
  15. SELECT
  16. last_name,
  17. employee_id,
  18. job_id,
  19. salary
  20. FROM
  21. employees
  22. WHERE
  23. salary < ALL ( SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG' )
  24. AND job_id <> 'IT_PROG';
  25. SELECT
  26. last_name,
  27. employee_id,
  28. job_id,
  29. salary
  30. FROM
  31. employees
  32. WHERE
  33. salary < ( SELECT MIN(salary) FROM employees WHERE job_id = 'IT_PROG' )
  34. AND job_id <> 'IT_PROG';

行子查询

  1. -- 查询员工编号最小并且工资最最高的员工信息。
  2. SELECT
  3. *
  4. FROM
  5. employees
  6. WHERE
  7. employee_id = ( SELECT MIN( employee_id ) FROM employees )
  8. AND salary = ( SELECT MAX( salary ) FROM employees );
  9. SELECT
  10. *
  11. FROM
  12. employees
  13. WHERE
  14. ( employee_id, salary ) = ( SELECT MIN( employee_id ), MAX( salary ) FROM employees );

SELECT 后面

仅支持标量子查询。

  1. -- 查询每个部门的员工个数。
  2. SELECT
  3. d.*,
  4. ( SELECT COUNT(*) FROM employees AS e WHERE e.department_id = d.department_id ) AS count
  5. FROM
  6. departments AS d;
  7. -- 查询员工号 = 102 的部门名。
  8. SELECT
  9. ( SELECT department_name FROM departments AS d INNER JOIN employees AS e ON d.department_id = e.department_id WHERE e.employee_id = 102 ) AS NAME;

FROM 后面

  1. -- 查询每个部门的平均工资的工资等级。
  2. SELECT
  3. ag_dep.*,
  4. g.grade_level
  5. FROM
  6. ( SELECT AVG( salary ) AS ag, department_id FROM employees GROUP BY department_id ) AS ag_dep
  7. INNER JOIN job_grades AS g ON ag_dep.ag BETWEEN lowest_sal
  8. AND highest_sal;

EXISTS 后面

语法:EXISTS(完整的查询语句)。

  1. -- 查询有员工的部门名。
  2. SELECT
  3. department_name
  4. FROM
  5. departments AS d
  6. WHERE
  7. EXISTS ( SELECT * FROM employees AS e WHERE d.department_id = e.department_id );
  8. -- 查询没有女朋友的男生信息。
  9. SELECT
  10. bo.*
  11. FROM
  12. boys AS bo
  13. WHERE
  14. bo.id NOT IN ( SELECT boyfriend_id FROM beauty );
  15. SELECT
  16. bo.*
  17. FROM
  18. boys AS bo
  19. WHERE
  20. NOT EXISTS ( SELECT boyfriend_id FROM beauty AS b WHERE bo.id = b.boyfriend_id );

参考: