子查询

1. 什么是子查询?

子查询(Subquery)是嵌套在另一个查询中的查询。它可以出现在 SELECT、FROM、WHERE 等子句中,用于从数据库中获取数据或进行复杂的条件过滤。子查询可以返回单个值、一列值或一个表。

1.1 子查询的类型

子查询主要分为以下几种类型:

  • 标量子查询(Scalar Subquery):返回单个值的子查询。
  • 列子查询(Column Subquery):返回一列值的子查询。
  • 行子查询(Row Subquery):返回一行值的子查询。
  • 表子查询(Table Subquery):返回一个表的子查询。

2. 子查询的基本语法

子查询的基本语法如下:

SELECT column_name
FROM table_name
WHERE column_name operator (SELECT column_name FROM table_name WHERE condition);

其中:

  • operator 可以是 =, >, <, >=, <=, <>, IN, NOT IN, ANY, ALL 等。
  • 子查询必须用括号 () 括起来。

3. 子查询的示例

3.1 标量子查询

标量子查询返回单个值,通常用于 WHERE 子句中。

示例: 查找工资高于平均工资的员工。

SELECT employee_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

3.2 列子查询

列子查询返回一列值,通常用于 IN 或 NOT IN 子句中。

示例: 查找在特定部门工作的员工。

SELECT employee_name
FROM employees
WHERE department_id IN (SELECT department_id FROM departments WHERE department_name = 'Sales');

3.3 行子查询

行子查询返回一行值,通常用于 IN 或 NOT IN 子句中。

示例: 查找工资最高的员工。

SELECT employee_name, salary
FROM employees
WHERE (salary, department_id) = (SELECT MAX(salary), department_id FROM employees GROUP BY department_id);

3.4 表子查询

表子查询返回一个表,通常用于 FROM 子句中。

示例: 查找每个部门的平均工资。

SELECT department_name, avg_salary
FROM (SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id) AS dept_avg
JOIN departments ON dept_avg.department_id = departments.department_id;

4. 子查询的注意事项

  • 性能问题:子查询可能会影响查询性能,尤其是在嵌套多层子查询时。应尽量简化子查询或使用连接(JOIN)来替代。
  • 相关子查询:相关子查询(Correlated Subquery)是指子查询依赖于外部查询的某个值。相关子查询的执行效率通常较低,应谨慎使用。

5. 实践练习

练习 1:标量子查询

任务:查找工资高于公司平均工资的员工。

提示:使用标量子查询计算公司平均工资。

SELECT employee_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

练习 2:列子查询

任务:查找在销售部门工作的员工。

提示:使用列子查询获取销售部门的 department_id。

SELECT employee_name
FROM employees
WHERE department_id IN (SELECT department_id FROM departments WHERE department_name = 'Sales');

练习 3:行子查询

任务:查找每个部门的最高工资员工。

提示:使用行子查询获取每个部门的最高工资。

SELECT employee_name, salary
FROM employees
WHERE (salary, department_id) = (SELECT MAX(salary), department_id FROM employees GROUP BY department_id);

练习 4:表子查询

任务:查找每个部门的平均工资。

提示:使用表子查询计算每个部门的平均工资。

SELECT department_name, avg_salary
FROM (SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id) AS dept_avg
JOIN departments ON dept_avg.department_id = departments.department_id;

6. 总结

子查询是 SQL 中强大的工具,能够帮助我们处理复杂的查询需求。通过本教程,你应该已经掌握了子查询的基本概念、类型、语法和使用场景。在实际应用中,合理使用子查询可以大大提高查询的灵活性和效率。

继续练习和探索,你将能够更加熟练地运用子查询来解决各种数据库查询问题。