2015-05-17 107 views
1

我在理解NOT EXISTS和子查询的组合如何工作时遇到问题。与NOT EXISTS和子查询混淆

据我所知,通过添加NOT EXISTS,查询将返回子查询不会查询的所有行。我不明白的是当我们在以下情况下使用它时它是如何工作的。

+-------------+--------+ 
| id_employee | salary | 
+-------------+--------+ 
| E001  | 1000 | 
| E002  | 1001 | 
| E003  | 999 | 
| E004  | 1001 | 
+-------------+--------+ 

,并尝试以下查询:

SELECT E.id_employee, E.salary 
FROM Employees E 
WHERE NOT EXISTS (
    SELECT F.id_employee 
    FROM Employees F 
    WHERE F.salary > E.salary 
); 

将返回:

+-------------+--------+ 
| id_employee | salary | 
+-------------+--------+ 
| E002  | 1001 | 
| E004  | 1001 | 
+-------------+--------+ 

好了,我真的不明白,了解F.salary > E.salary比较是如何工作的,因为如果它比较逐行排列这两个表(它们是相同的),对我来说根本没有意义返回任何行。

你能否告诉我这是如何工作的?

回答

1

NOT EXISTS通常与相关子查询一起使用,即Outer和Inner查询之间存在关联(并且不能在没有“找不到表格”的情况下运行子查询代码)。你的例子是相关的,但以一种奇怪的方式。

按道理它的处理是这样的:

在雇员表运行的每一行下面的查询:

SELECT F.id_employee 
FROM Employees F 
WHERE F.salary > <salary of the current row> 

如果该查询不返回任何行(即没有薪水高于当前薪水的行)NOT EXISTS的计算结果为true,并从employee表中返回此行。

实际上,此查询返回薪水最低的行。

的相关EXISTS是神似JOINNOT EXISTS是一种反连接,只有那些不能加入将返回的行。这是常见的用法,找到第二个表中不存在的值的行,例如查找具有无效/不存在的部门编号的雇员

SELECT * 
FROM Employees E 
WHERE NOT EXISTS (
    SELECT * 
    FROM Departments D 
    WHERE E.department_number = D.department_number 
); 
0

因为你在你的子查询中不指定任何其他条件比:

F.salary > E.salary 

您从E获得任意行那里是在F具有薪水高则没有其他入口。由于E002E004的薪水均为1001,而其他人的薪水均不高于1001,因此返回E002E004

如果您改变WHERE是:

F.salary >= E.salary 

你会得到任何记录的回报因为每个人都有工资是小于或等于其他员工的薪水。

0

好吧,WHERE子句是针对每一行进行评估的。 WHERE子句将仅返回谓词计算结果为TRUE的那些行。你的谓词是

NOT EXISTS (
    SELECT F.id_employee 
    FROM Employees F 
    WHERE F.salary > E.salary 
); 

所以结果集将只包含行,其中该谓词进行评估,以TRUE。对于工资为1000的第1行,存在工资较大的行,因此该行的谓词是FALSE,并且它从结果集中消除。 Fom的第二行薪水为1001,并且没有其他行的薪水较高,因此此行的谓词计算结果为TRUE,此行将在结果集中。