跳转到主要内容
模块 4 · 第 4 课(共 4)课程中的16/57~12 min
模块课程(4/4)

一个查询嵌套在另一个查询中:子查询

您已经学习了如何提取、过滤、分组、连接和转换。那里 最后一个基本思想是:将一个查询放入另一个查询。这些是 称为子查询,它们是让您回答问题的步骤 比如*“谁的收入高于平均水平?”或“哪些部门有人 分配给一个项目?"*.

基本语法

子查询是用括号括起来的 SELECT,用于代替单个查询 另一个查询中的值或值列表:

SQL
-- Find who earns MORE THAN THE COMPANY AVERAGE:
SELECT first_name, last_name, salary
FROM   employees
WHERE  salary > (SELECT AVG(salary) FROM employees);

引擎首先运行子查询 - SELECT AVG(salary) FROM employees 返回单个数字 — 然后在外部 WHERE 中使用该数字 就好像你是手写的一样。这正是优点:你可以 不需要提前知道平均值,SQL 会为您计算出来。

最常见的三种“类型”

1.子查询返回单个值

上面的例子:子查询产生一行,一列(称为 标量)。您可以将其与 =、>、< 等一起使用。

SQL
-- Employee with the highest salary:
SELECT first_name, last_name
FROM   employees
WHERE  salary = (SELECT MAX(salary) FROM employees);

2. 子查询返回列表

子查询生成一列,许多行。你用它与 IN (...):

SQL
-- Departments that have at least one employee:
SELECT name
FROM   departments
WHERE  id IN (SELECT DISTINCT department_id
              FROM employees
              WHERE department_id IS NOT NULL);

3.子查询作为“表”(FROM)

子查询还可以代替 FROM 中的表。这是有用的 预先计算聚合,然后过滤或连接它们:

SQL
-- Departments with average salary above 40000:
SELECT d.name, medie.stipendio_medio
FROM   departments AS d
JOIN  (SELECT department_id, AVG(salary) AS stipendio_medio
       FROM employees
       GROUP BY department_id) AS medie
   ON d.id = medie.department_id
WHERE  medie.stipendio_medio > 40000;

子查询还是 JOIN?何时使用哪个

通常可以使用 JOIN 或子查询获得相同的结果。 经验法则:

  • 根据另一个表的属性过滤一个表的行 (“部门的员工……”),IN (subquery) 非常具有可读性。
  • 要组合结果中多个表中的列,请使用 JOIN。
  • 计算聚合并将其用作阈值(“高于 average"),标量子查询是自然的选择。

在实践中,您会看到两者:SQL 引擎通常对它们进行相同的优化 方式。选择可读性最好的形式。

尝试一下

锻炼#sql.m4.l4.e1
尝试:0加载中...

查找收入严格高于公司平均水平的员工的名字 (first_name)、姓氏 (last_name) 和薪水 (salary)。三列。

正在加载编辑器...
显示提示

代替 ?使用子查询 SELECT AVG(salary) FROMEmployees — 它返回一个数字用作阈值。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m4.l4.e2
尝试:0加载中...

列出至少有一名员工的工资严格大于 50000 的部门名称 (departments.name)。使用带有 IN 的子查询。按字母顺序排列。

正在加载编辑器...
显示提示

内部子查询返回工资 > 50000 的员工的部门 id。然后在外部查询上使用 WHERE id IN (...)。

3 次尝试后可用的解决方案