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

带有值列表的子查询

你还记得我们曾经有过一个任务——从一个表中找到所有在另一个表中没有对应记录的记录吗?

还有这张图:

如果我没记错的话,任务如下:显示员工表中没有任务的所有员工的列表

让我们也分两步找到解决方案。

首先,让我们编写一个查询,返回在任务表中有任务的所有员工的 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 
   )