有人可以解释这个查询

时间:2012-04-05 16:11:18

标签: sql oracle

这是查询

SELECT * FROM customers  
WHERE 
     NOT EXISTS 
     (     
          SELECT 1 FROM brochure_requests     
          WHERE  brochure_requests.first_name = customers.customer_first_name AND    
          brochure_requests.last_name = customers.customer_last_name
     )

这个查询工作得很好,但我不确定它为什么会起作用。在NOT EXISTS部分SELECT 1中, 1 是什么。当我运行此查询时

select 1 from test2

以下是结果:

1
-----
1
1
1
1
1
1
1
1
1
1
1
..

不存在的查询如何工作?

8 个答案:

答案 0 :(得分:3)

编译器非常聪明,可以忽略SELECT中的实际EXISTS。所以,基本上,如果它因为过滤器匹配而返回行,那就是它所关心的...... SELECT的{​​{1}}部分永远不会执行。它仅将EXISTS子句用于评估目的

我有这种误解很长一段时间,因为你会看到很多EXISTS。但是,我已经看过42,*等....它从来没有真正关心结果,只有那里会有一个:)。要记住SQL是一种编译语言的关键,所以它会适当地优化它。

你可以放一个1/0,它不会抛出被零除的异常......因此进一步证明了结果集没有被评估。这显示在this SQLFiddle

来自小提琴的代码:

SELECT 1

最后,更重要的是,CREATE TABLE test (i int) CREATE TABLE test2 (i int) INSERT INTO test VALUES (1) INSERT INTO test2 VALUES (1) SELECT i FROM test WHERE EXISTS ( SELECT 1/0 FROM test2 WHERE test2.i = test.i ) 只是否定NOT,向IGNORE说任何匹配的行

答案 1 :(得分:1)

子查询是correlated subquery加入所选字段的customersbrochure_requests表格。

EXISTS子句只是一个只返回匹配行的谓词(而NOT否定了这一行。)

答案 2 :(得分:0)

查询:

select 1 from test2

显示值1作为test2表中所有记录的值。

每个SELECT查询必须至少包含一列。我认为这就是为什么在这里使用一个值为1的未命名列。

子查询为您提供表brochure_requests中相关客户的行。

NOT EXISTS导致主查询返回Customers表中的所有行,这些行不在表brochure_requests中。

答案 3 :(得分:0)

有问题的关系运算符称为'antijoin'(或者“不匹配”或“半差异”)。在自然语言中:使用公共属性first_name和last_name匹配brochure_requests的客户。

密切相关的运算符是关系差异(或者“减”或“除”),例如在SQL

SELECT customer_last_name, customer_first_name
  FROM customers  
EXCEPT
SELECT last_name, first_name  
  FROM brochure_requests;

答案 4 :(得分:-1)

这是简单的检查,如果存在行,它将返回1,只需要检查它是否存在,仅此而已。

答案 5 :(得分:-1)

如果客户要求提供小册子,子查询将为此客户返回1。并且不会将此客户添加到返回结果集中。 bcouse of NOT EXISTS条款。

答案 6 :(得分:-1)

注意:我不了解Oracle,并且不是SQL专家。

但是,SELECT 1 from只会为匹配1子句的每一行返回from。因此内部select可以找到brochure_requests行,其名称字段与当前正在考虑的customer行的名称字段匹配,它将产生1结果并使{{1}失败}}

因此,查询会选择没有NOT EXISTS匹配其姓名的所有customers

答案 7 :(得分:-2)

对于表Customers的每一行,查询返回sub-query时的行。 NOT EXISTS不返回任何行。

如果NOT EXISTS中的子查询返回行,则不会返回表Customers的行。