模块 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 次尝试后可用的解决方案