Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 将不在转换为不存在_Sql_Oracle - Fatal编程技术网

Sql 将不在转换为不存在

Sql 将不在转换为不存在,sql,oracle,Sql,Oracle,有一个噩梦般的时间来理解NOT EXISTS的用法,主要是如何在下面的解决方案中转换我的NOT,以便我能够真正理解我是如何实现结果的。 有几篇关于askTom、oracle论坛和stackoverflow的文章,但找不到任何有助于理解此问题的文章。如果我在noobish搜索中错过了它,我深表歉意 SELECT s.S_Fname, s.S_Lname FROM STUDENT s WHERE s.S_Sex = 'F' AND S.S_Id NOT IN(SELECT e.S_Id

有一个噩梦般的时间来理解NOT EXISTS的用法,主要是如何在下面的解决方案中转换我的NOT,以便我能够真正理解我是如何实现结果的。 有几篇关于askTom、oracle论坛和stackoverflow的文章,但找不到任何有助于理解此问题的文章。如果我在noobish搜索中错过了它,我深表歉意

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id
        FROM ENROLLMENT e
        WHERE e.Mark < 70);

在内容上提供一点帮助,试图找到那些在所注册的任何班级中从未获得低于70分的女生。

当你掌握窍门时,这相当简单:

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id           -- take this line
        FROM ENROLLMENT e
        WHERE e.Mark < 70);
可能的微小变化是认识到选择e.S_Id。。。实际上不需要e.S_Id。具有EXISTS和not EXISTS的子查询只需检查是否返回了行,列值无关紧要。您可以将SELECT*或常量放入其中,选择1是公共的,或者选择NULL,甚至选择1/0“是”,这将起作用!:

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT 1
        FROM ENROLLMENT e
        WHERE e.Mark < 70  
        AND S.S_Id = e.S_Id);
另一个主要考虑因素是,当您以这种方式进行转换时,只有当两个S_Id列都不可为空时,表面上等价的不存在,并且在查询的编写中不存在的才是真正等价的。如果e.S_Id列可为空,则NOT IN可能导致整个查询不返回任何行,因为x不在a、b、c、。。。相当于xa和xb以及。。。当a,b,c中的一个。。。是空的

出于类似的原因,如果s.s_Id可为空,则会得到不同的结果。在本例中,这不太可能,因为它可能是主键,但在其他情况下,它很重要


因此,使用NOT EXISTS几乎总是更好的,因为即使任一列都可以为null,它的行为也会有所不同。s.s_Id=e.s_Id检查将在前面丢弃具有null的行,通常这种行为是需要的。问题中有许多细节:,在@Martin Smith的回答中。您还可以找到将NOT IN转换为NOT EXISTS的方法,并保持与null相关的不愉快行为。

这不完全是您所要求的,但这里有一种方法可以在不存在NOT EXISTS的情况下实现这一点-创建“70岁以下的成就者”作为派生表,左外连接它并检查是否有空值,如下图所示

SELECT s.S_Fname, s.S_Lname 
FROM STUDENT s
LEFT JOIN
(
  SELECT S_Id 
  FROM ENROLLMENT
  WHERE Mark < 70
) e ON e.S_Id = s.S_Id
WHERE e.S_Id IS NULL 
AND s.S_Sex = 'F';
也可能有助于您对SQL的一般理解。这两种方法都有利弊


精彩的你是对的,现在看解决方案时,这是非常有意义的。not exists子句乍一看有点痛苦,但一旦您了解如何消除不必要的行,它就会像一个符咒一样工作。谢谢+1您可能会注意到,在许多情况下,乐观主义者无论如何都会将它们转换为相同的执行计划-我认为只有在e.s_id不为null的情况下,这是确保该id不为null的另一个很好的理由。我没有看到您的查询中不存在的部分。OP想了解不存在的问题。它只是帮助OP扩大对SQL理解的另一种解决方案。
SELECT s.S_Fname, s.S_Lname 
FROM STUDENT s
LEFT JOIN
(
  SELECT S_Id 
  FROM ENROLLMENT
  WHERE Mark < 70
) e ON e.S_Id = s.S_Id
WHERE e.S_Id IS NULL 
AND s.S_Sex = 'F';