SQL 中的嵌套查询
SQL 语言允许您将一个查询嵌套在另一个查询中。这使得编写一个非常大的查询成为可能,该查询将执行大型和复杂的操作,尽管代码的可读性大大降低。
根据子查询返回的值的多少,它们可以应用的区域会发生变化。一共有三个选项:
- 子查询返回一个单一值(一列和一行)。
- 子查询返回一个值列表(一个只有一列的表)。
- 子查询返回一个表(许多列,任意数量的行)。
让我们看一下每种情况的一个例子。
带有标量结果的子查询
让我们从员工表中找出薪水高于公司平均水平的所有员工的列表。我们该怎么做?
如果我们事先知道,我们可以通过将他们的工资与平均工资进行比较来轻松过滤员工。同时,我们已经编写了一个查询,可以让我们计算公司员工的平均工资。让我们记住它:
SELECT AVG(salary) FROM employee
然后 MySQL 返回给我们值:76833.3333。
现在如何找到工资高于平均水平的所有员工的列表?这也很简单:
SELECT * FROM employee
WHERE salary > 76833.3333
此查询的结果将是:
ID | 姓名 | 职业 | 薪水 |
---|---|---|---|
1个 | 伊万诺夫伊万 | 程序员 | 100000 |
2个 | 彼得罗夫彼得 | 程序员 | 80000 |
4个 | 拉比诺维奇·莫伊沙 | 导演 | 200000 |
现在我们只是通过替换第一个请求而不是值 76833 来组合两个请求:
SELECT * FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee)
此查询的结果将是相同的:
ID | 姓名 | 职业 | 薪水 |
---|---|---|---|
1个 | 伊万诺夫伊万 | 程序员 | 100000 |
2个 | 彼得罗夫彼得 | 程序员 | 80000 |
4个 | 拉比诺维奇·莫伊沙 | 导演 | 200000 |
带有值列表的子查询
你还记得我们曾经有过一个任务——从一个表中找到所有在另一个表中没有对应记录的记录吗?
还有这张图:
![](https://cdn.codegym.cc/images/article/a0eff64c-0bb4-4480-833e-c1305cd03a5e/512.jpeg)
如果我没记错的话,任务如下:显示员工表中没有任务的所有员工的列表。
让我们也分两步找到解决方案。
首先,让我们编写一个查询,返回在任务表中有任务的所有员工的 ID。只要记住两件事:
- 删除重复项 - 使用 DISTINCT 关键字。
- 从结果中移除 NULL 值。
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
在这里,我们得到了这样一个请求的漂亮结果:
员工ID |
---|
1个 |
2个 |
5个 |
4个 |
6个 |
为了方便,我们暂时记为一个序列:1,2,5,4,6。现在让我们编写第二个查询 - 到 employee 表,它将返回其 id 不包含在第一个列表中的员工列表:
SELECT * FROM employee
WHERE id NOT IN (1,2,5,4,6)
这个查询的结果是:
ID | 姓名 | 职业 | 薪水 | 年龄 | 加入日期 |
---|---|---|---|---|---|
3个 | 伊万诺夫谢尔盖 | 测试员 | 40000 | 三十 | 2014-01-01 |
现在,与前面的示例一样,您可以通过简单地替换第一个请求的主体而不是 id 列表来合并两个请求。
SELECT * FROM employee
WHERE id NOT IN (
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
)
GO TO FULL VERSION