Coursera 笔记

Module 03 · Intermediate SQL

Sub-Queries and Nested Selects嵌套查询 (Subqueries) 详解

Coursera ↗

您好,欢迎学习本视频,您将了解如何编写子查询 (Subqueries) 或嵌套 SELECT 语句 (Nested Select Statements)。

什么是子查询?

子查询 (Subqueries),也称为子选择 (Sub-selects),是像常规查询一样,但被放置在圆括号内并嵌套在另一个查询中的查询。这使得您可以构建比单独查询更强大的查询。

  • 嵌套示例: 如下图所示,子查询位于另一个查询的 WHERE** 子句**中。

在本课中,我们将使用一个包含 Employee_ID、First_Name、Last_Name、Salary 等列的 EMPLOYEES** 表**作为示例。


1 在WHERE子句中使用子查询

当聚合函数(如 AVG)不能直接在 WHERE 子句中评估时,子查询是解决此类限制的有效方法。

场景:查询薪资高于平均水平的员工

如果我们尝试直接使用聚合函数,查询会出错:

SQL

SELECT * FROM EMPLOYEES WHERE Salary > AVG(Salary); 

❌ 结果: 运行此查询会导致错误,指示聚合函数使用无效。内置聚合函数(如 AVG)的限制之一是它们不能总是直接在 WHERE 子句中评估。

解决方法:使用子查询绕过限制

通过将聚合函数放在子查询中,可以先计算出平均薪资,再用于外部查询的 WHERE 子句进行比较:

SQL

SELECT Employee_ID, First_Name, Last_Name, Salary 
FROM EMPLOYEES 
WHERE Salary > (SELECT AVG(Salary) FROM EMPLOYEES); 

  • 原理: 子查询首先计算出平均薪资,然后外部查询使用这个单一值作为 WHERE 子句的比较条件,从而绕过了聚合函数不能直接在 WHERE 子句中评估的限制。

2 在SELECT列列表中使用子查询(列表达式)

子查询不仅可以放在 WHERE 子句中,还可以放在要选择的列列表中。这类子查询被称为列表达式 (Column Expressions)。

场景:比较每位员工的薪资与平均薪资

如果我们想将每位员工的薪资与平均薪资进行比较,直接尝试如下查询会出错:

SQL

SELECT Employee_ID, Salary, AVG(Salary) AS Average_Salary FROM EMPLOYEES;

❌ 结果: 运行此查询将导致错误,指示未指定 GROUP BY 子句。

解决方法:使用子查询作为列表达式

我们可以将 AVG 函数放入一个子查询中,并将其放置在列列表中:

SQL

SELECT Employee_ID, Salary, 
    (SELECT AVG(Salary) FROM EMPLOYEES) AS Average_Salary 
FROM EMPLOYEES;

  • 原理: 子查询作为一个列表达式,为外部查询返回的每一行计算并重复显示平均薪资。

3 在FROM子句中使用子查询(派生表)

子查询还可以作为 FROM** 子句的一部分。这类子查询有时被称为派生表 (Derived Tables)** 或表表达式 (Table Expressions),因为外部查询将子查询的结果用作其数据源。

场景:基于非敏感信息创建派生表

假设我们想创建一个只包含非敏感员工信息的派生表:

SQL

SELECT * FROM 
    (SELECT Employee_ID, First_Name, Last_Name, Department_ID FROM EMPLOYEES) AS Employee_For_All;

  • 子查询 (内查询): SELECT Employee_ID, First_Name, Last_Name, Department_ID FROM EMPLOYEES
    • 该子查询排除了敏感字段(如出生日期或薪资)。
  • 外部查询: SELECT * FROM (...) AS Employee_For_All
    • 外部查询使用子查询的结果集作为一个临时表(Employee_For_All)。

虽然上例相对简单,但派生表在处理多表连接 (joins)** 或复杂情况时,能够极大地增强查询能力。


总结

在本视频中,您了解了子查询和嵌套查询如何用于形成更丰富的查询,并克服聚合函数的一些限制。

您学习了在以下位置使用子查询:

  • WHERE** 子句**
  • 列列表(列表达式)
  • FROM** 子句**(派生表/表表达式)