我刚学会(昨天)使用的"存在"代替""。

 BAD
 select * from table where nameid in ( 
          select nameid from othertable where otherdesc =  'SomeDesc' )      
 GOOD
 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      

和我有一些问题有关:

1)在解释我的理解是: "为什么这是最好的是因为只有匹配的价值将会返回,而不是建立一个大规模的清单的可能结果".这是不是意味着,虽然第一个子查询可能会返回900结果的第二次会回只有1(是或否)?

2)在过去,我有RDBMS抱怨:"仅在第1000行可能被检索",这第二种办法会解决这一问题?

3)的范围是什么别在第二次查询?...没别的只生活在括号?

例如

 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      
 AND 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeOtherDesc' )      

也就是说,如果我使用相同的别名(o表))在第二个"存在"会不会存在任何问题的第一存在?或者是他们完全独立?

这是什么Oracle仅关系或者它是否有效用于最RDBMS?

非常感谢

有帮助吗?

解决方案

这是具体到每一个DBMS并取决于所查询的优化。有一些优化检测在条款并把它翻译。

在所有DBMSes我测试了,别名是唯一有效的内部()

顺便说一句,你可以改写作为查询:

select t.* 
from table t 
join othertable o on t.nameid = o.nameid 
    and o.otherdesc in ('SomeDesc','SomeOtherDesc');

并且,回答您的问题:

  1. 是的
  2. 是的
  3. 是的

其他提示

您正在进入复杂的领域,称为“相关子查询”。由于我们没有关于您的表格和关键结构的详细信息,因此一些答案只能是“可能”。

在您的初始IN查询中,无论OtherTable是否包含列NameID(并且确实,OtherDesc是否作为Table或OtherTable中的列存在),该表示法都是有效的 - 这在您的任何示例中都不清楚,但可能是是OtherTable的一列。此行为是将相关子查询转换为相关子查询的原因。当人们第一次遇到焦虑时,这也是一种常见的焦虑源 - 总是偶然发生。由于SQL标准要求将子查询中的名称解释为引用外部查询中的列,如果子查询中提到的表中没有相关名称的列,但是有一个列外部(主)查询中提到的表中的相关名称,没有想要声明符合(这一点)SQL标准的产品将做任何不同的事情。

您的Q1的答案是“它取决于”,但是给出了合理的假设(NameID在两个表中都作为列存在; OtherDesc仅存在于OtherTable中),结果应该与返回的数据集相同,但在表现方面可能并不相同。

你的Q2的答案是,在过去,你使用的是劣质的,如果没有缺陷的DBMS。如果它支持EXISTS,那么DBMS可能仍会抱怨结果的基数。

应用于第一个EXISTS查询的Q3的答案是“t在整个语句中作为别名可用,但o仅作为括号内的别名”使用。应用于你的第二个示例框 - 使用AND连接两个子选择(当我查看它时,第二个缺少打开的括号),然后“t”在整个语句中作为别名可用并引用同一个表,但有两个不同的别名都标记为'o',每个子查询一个“。请注意,如果OtherDesc对于OtherTable中的给定NameID值是唯一的,则查询可能不返回任何数据;否则,它需要在OtherTable中有两行具有相同的NameID,并且Table中每行的两个OtherDesc值都需要具有该NameID值。

  1. Oracle的特定:当你写查询使用的条款,你告诉基于规则的优化,你想要的内部查询,以动外查询。当你写存在于其中的条款,你说的是优化那你想要的外部查询将首先开始运行,使用每种价值来获取一个数值从内部查询。看看 "之间的差以及存在子查询".
  2. 大概。
  3. 别宣布的内部查询生活在子查询。顺便说一下,我不认为你的例子与2And子查询是否有效SQL。你是说联盟,而不是?

我个人会使用连接,而不是子查询。

SELECT t.*
FROM yourTable t
    INNER JOIN otherTable ot
        ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc')

很难概括EXISTS总是优于IN。从逻辑上讲,如果是这种情况,则SQL社区将用EXISTS替换IN ... 此外,请注意IN和EXISTS不相同,当您使用这两个时结果可能会有所不同......

使用IN,通常是内表的全表扫描一次而不删除NULL(所以如果你的内表中有NULL,默认情况下IN不会删除NULLS)...虽然EXISTS删除NULL并且在相关子查询,它为外部查询中的每一行运行内部查询。

假设没有NULLS及其简单查询(没有相关性),如果您找到的行不是最后一行,则EXIST可能会表现得更好。如果恰好是最后一行,EXISTS可能需要像IN一样扫描到最后..所以类似的性能......

但IN和EXISTS不可互换......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top