2012-04-05 133 views
1

这里是查询有人可以解释这个查询

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什么是。当我运行此查询

select 1 from test2 

这里是结果:

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

如何在不存在查询工作?

回答

3

编译器足够聪明,可以忽略EXISTS中的实际SELECT。所以,基本上,如果它会因为过滤器匹配而返回行,这就是它所关心的...... EXISTSSELECT部分永远不会执行。它只使用EXISTS子句进行评估

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

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

代码所示,从小提琴:

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简单地否定一个EXISTS,说要忽略匹配任何行

+0

Wow..thanks这个交代 – Luke101 2012-04-05 17:04:40

-1

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

+0

的存在实际上并不返回任何东西。 – 2012-04-05 16:18:52

+0

如果它没有返回任何东西,它只是表示没有查询被匹配,你的查询条件是常见的“if exists condition”,当我们只需要检查该行是否存在时,不需要返回某些东西,只检查是否存在否则,这就是为什么子查询中有一个“1”。 – Elkan 2012-04-05 16:21:14

+0

不,我在说的是EXISTS子查询实际上并不返回1.它仅仅用作评估的一种手段。请参阅我的答案小提示以获得证明 – 2012-04-05 16:23:05

1

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

EXISTS子句只是一个谓词,它只返回匹配的行(并且NOT否定那个)。

-1

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

+0

子查询实际上并没有返回任何东西 – 2012-04-05 16:17:08

-1

注意:我不认识Oracle,也不是SQL方面的专家。

但是,SELECT 1 from只需为匹配from子句的每一行返回一个1。所以内部select可以找到一个brochure_requests行,其名称字段与当前正在考虑的customer行的名称字段相匹配,它将生成1结果,并且失败NOT EXISTS

因此,查询选择所有customers谁没有匹配他们的名字brochure_request

+0

需要注意的是SELECT部分​​永远不会被评估,所以它实际上不会产生1 – 2012-04-05 16:30:42

-2

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

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

+0

子查询实际上并不返回任何东西。它仅用于评估目的 – 2012-04-05 16:45:01

0

查询:

select 1 from test2 

显示您作为在TEST2表中的所有记录值的值为1。

每个SELECT查询必须至少有一列。我认为这就是为什么在这里使用具有值1的匿名列的原因。

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

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

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; 
相关问题