SQL中的NOT EXISTS子句

时间:2013-02-25 07:31:04

标签: sql not-exists

我一直坚持查询,我真的无法想象执行是如何发生的,任何帮助都将受到高度赞赏:

设计查询是为了查找处理所有项目的员工的详细信息。

查询是:

SELECT E.LNAME, E.FNAME
FROM EMPLOYEE E
WHERE NOT EXISTS
(
    SELECT PNUMBER
    FROM PROJECT
    WHERE PNUMBER NOT EXISTS 
    (
        SELECT PNO 
        FROM WORKS_ON
        WHERE ESSN=E.SSN 
    ) 
);

数据库结构是:

包含列的表项目:

  

Pname,Pnumber,Plocation和dnum

表works_on with columns:

  

ESSN,PNO和HOURS

表员工列:

  

Fname,minit,Lname,SSN,Bdate,地址,性别,工资,superssn和dno

如果有人能用简单的词语解释这个查询是如何执行的,那将非常有帮助。

3 个答案:

答案 0 :(得分:9)

如果子查询返回至少一行,则SQL EXISTS条件被视为“满足”。

因此,通过暗示NOT EXISTS,我们希望子查询返回零行,所以使用这些知识让我们看看你的查询

SELECT E.LNAME, E.FNAME
FROM EMPLOYEE E
WHERE NOT EXISTS (SELECT PNUMBER
FROM PROJECT
WHERE PNUMBER NOT EXISTS (SELECT PNO 
FROM WORKS_ON
WHERE ESSN=E.SSN ) );

有两个嵌套的NOT EXISTS语句,SQL必须以相反的顺序运行它们,因为一个依赖于另一个。第一个将被查询的是这一个(最后一个):

SELECT PNO 
    FROM WORKS_ON
    WHERE ESSN=E.SSN

如果这返回零行(因为我们已经说过NOT EXISTS),那么它将运行下一个查询,它将是:

SELECT PNUMBER
    FROM PROJECT

同样,这必须返回零行,如果是,那么它将运行最后一个查询,这是第一个。

SELECT E.LNAME, E.FNAME
FROM EMPLOYEE E

实质上,每个“NOT EXIST”子查询必须为前面的查询返回零行才能运行,否则最终会有0行(没有结果)。

有关EXISTS条件的更多信息here

答案 1 :(得分:1)

我知道这是一个老问题,但我很感兴趣所以我花了一些时间在它上面,让努力失去将是一种浪费。

首先,我不知道内部<column name> NOT EXISTS <subquery>的语法,但它似乎等同于<column name> NOT IN <subquery>。只是这个概念使我的查询更加全面,因为它更清楚地将内部查询链接到 PROJECT 。 所以我从

开始
SELECT E.LNAME, E.FNAME
FROM EMPLOYEE E
WHERE NOT EXISTS
(
    SELECT PNUMBER
    FROM PROJECT
    WHERE PNUMBER NOT IN
    (
        SELECT PNO
        FROM WORKS_ON
        WHERE ESSN=E.SSN
    )
);

步骤细分:

  • 内部查询只列出员工处理的所有项目编号。

            SELECT PNO
            FROM WORKS_ON
            WHERE ESSN=E.SSN
    
  • 中间查询采用补码。结果是您的员工无法处理的所有项目编号。

        SELECT PNUMBER
        FROM PROJECT
        WHERE PNUMBER NOT IN
        (
            -- projects that the employee works on
        )
    
  • 如果存在员工不工作的项目,那么他不会对所有项目都有效,因此他不应该被包括在结果中。

    SELECT E.LNAME, E.FNAME
    FROM EMPLOYEE E
    WHERE NOT EXISTS
    (
        -- projects that the employee does not work on
    )
    

答案 2 :(得分:0)

keyszers的答案对于这个问题已经绰绰有余了。但是我想补充几点

SQL查询的执行从内部查询开始。因此,在您的Query中,where子句中的一个执行第一个

  

哪里没有PNUMBER           (               选择PNO               来自WORKS_ON               在哪里ESSN = E.SSN           )

根据上述查询的结果,下面的其他查询将会运行。

WHERE NOT EXISTS (
    SELECT PNUMBER
    FROM PROJECT
    WHERE PNUMBER NOT EXISTS (**Resultset**)

总结我的观点 - 您需要根据子查询中的结果集调试查询。