【问题标题】:NOT EXISTS clause in SQLSQL 中的 NOT EXISTS 子句
【发布时间】:2013-02-10 07:20:27
【问题描述】:

我一直在查询,我真的无法思考执行是如何发生的,任何帮助将不胜感激:

该查询旨在查找参与所有项目的员工的详细信息。

查询是:

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

Table works_on 与列:

ESSN、PNO 和营业时间

带有列的员工表:

Fname,minit,Lname,SSN,Bdate,address,sex,salary,superssn 和 dno

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

【问题讨论】:

标签: sql not-exists


【解决方案1】:

如果子查询返回至少一行,则认为 SQL 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

如果这返回零行(因为我们说不存在),那么它将运行下一个查询,即:

SELECT PNUMBER
    FROM PROJECT

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

SELECT E.LNAME, E.FNAME
FROM EMPLOYEE E

本质上,每个“NOT EXIST”子查询都必须返回零行才能运行前面的查询,否则您将得到 0 行(无结果)。

关于 EXISTS 条件的更多信息here

【讨论】:

  • 谢谢。我明白了逻辑,但不确定输出将如何获取将在所有项目上工作的员工记录。考虑子查询:
【解决方案2】:

我知道这是一个老问题,但我很感兴趣,所以我花了一些时间来解决这个问题,如果让这些努力付诸东流,那就太浪费了。

首先,我不知道内部<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
    )
    

【讨论】:

    【解决方案3】:

    keyszers 的回答对于这个问题来说绰绰有余。不过我想补充几点

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

    号码不存在的地方 ( 选择 PNO FROM WORKS_ON 其中 ESSN=E.SSN )

    根据上面查询的结果,下面的另一个查询将运行。

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

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

    【讨论】:

      猜你喜欢
      • 2013-04-17
      • 2019-05-18
      • 2012-06-29
      • 2021-10-02
      • 2012-05-16
      • 2016-01-09
      • 2018-02-15
      • 1970-01-01
      • 2018-01-28
      相关资源
      最近更新 更多