SQL - 表别名范围

时间:2008-10-09 19:30:41

标签: sql scope table-alias

我刚学会(昨天)使用“存在”而不是“在”。

 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有效?

非常感谢

5 个答案:

答案 0 :(得分:4)

它特定于每个DBMS并依赖于查询优化器。一些优化器检测IN子句并将其翻译。

在我测试的所有DBMS中,别名仅在()

中有效

顺便说一句,您可以将查询重写为:

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

并回答你的问题:

答案 1 :(得分: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值。

答案 2 :(得分:2)

  1. 特定于Oracle:当您使用IN子句编写查询时,您告诉基于规则的优化器您希望内部查询驱动外部查询。当您在where子句中编写EXISTS时,您告诉优化器您希望首先运行外部查询,使用每个值从内部查询中获取值。见"Difference between IN and EXISTS in subqueries"
  2. 可能。
  3. 在子查询中声明的别名存在于子查询中。顺便说一下,我不认为你的2个ANDed子查询的例子是有效的SQL。你的意思是UNION而不是AND?

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

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

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

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