这是查询
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
..
不存在的查询如何工作?
答案 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加入所选字段的customers
和brochure_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
的行。