子查询的别名与主查询的别名相同


23

我有一个别名与其子查询别名相同的SQL查询。

例如:

select *
from ROOM r
where ...
         (
              select *
              from ROAD r
              where ...
         )

这很好用,因为子查询的别名似乎隐藏了主查询的别名。

  1. 在所有情况下都可以那样工作吗?
  2. 我会得到不确定的结果吗?
  3. 如果可以的话,如何引用主查询r呢?

1
简短的回答是“1.是”,“2.No”和“3.in这种情况下,你不能(所以它不是真的确定,如果你想这样的引用)”
ypercubeᵀᴹ

Answers:


15

嵌套的子查询使用与父查询相同的别名是可以的,尽管对于阅读代码的人来说可能会有些混乱。嵌套子查询上别名的名称空间与父项上的名称空间是分开的。例如,下面的查询具有一个嵌套的子查询b,该子查询中也b使用了别名。这可能会使程序员感到困惑,但使用DBMS引擎可以:

   select a.foo
          ,b.bar
          ,b.BarCount
      from (select b.bar
                  ,count (*) as BarCount
              from BarTable b
              join OtherTable o
                on b.OtherTableID = o.OtherTableID
             group by b.bar) b
      join Foobar a
        on a.bar = b.bar

在关联的子查询上,您可以访问父代的别名,因此别名在父查询和关联的子查询中必须是唯一的。如果我们采用一个相关的子查询(例如下面的查询),则在父查询和相关的子查询之间共享一个全局名称空间:

select a.foo
      ,b.bar
  from Foobar a
  join Bar b
    on b.FooBarID = a.FooBarID
 where not exists
       (select 1
          from Bar b2
         where b2.BarCategoryID = b.BarCategoryID
           and b2.BarDate > b.BarDate)

相关子查询没有别名,因为它不参与这样的联接1。子查询可以使用引用bb2bar因为相关子查询与父级共享别名的名称空间。


1请注意,尽管指定的实际操作是相关子查询,而不是针对嵌套子查询的联接,但优化器可能会选择在幕后的计划内使用联接运算符。


第一个查询中的子查询是派生表,标准SQL要求始终为其指定一个名称:没有逻辑上的要求,但SQL Server还是实现了该要求,尽管在特定示例中,您选择的名称确实是需要。第二个查询中的子查询不是派生表,因此为什么它不需要名称(它是相关子查询的事实并不重要)。
一天的时间

@onedaywhen-除了关联子查询外,我无法想到任何情况,在该关联子查询中,子查询需要访问父级中使用的别名。您有特定的想法吗?
ConcernedOfTunbridgeWells 2012年

我不确定我是否理解您的问题。也许我应该明确指出,我是在特别回应您的评论:“相关子查询没有别名,因为它不参与联接。” 我的回答是要传达出这样的观点:有关范围变量的规则(SQL标准称为“关联名称”,而您称为“别名”)与它们在联接中的参与(或其他)没有直接关系。
一天,2012年

简单的例子: SELECT * FROM ( SELECT c FROM T ) AS T2; -没有联接,没有关联,但是SQL标准要求为派生表分配一个范围变量(T2在这种情况下)。
一天,2012年

3

在ConcernedOfTunbridgeWells上,您要编写(强调我的意思):“在相关子查询上,您可以访问父级的别名,因此别名在父级查询和相关子查询中必须是唯一的。”

我不认为需要唯一性。我相信,如果在关联子查询中使用别名作为关联名称,以及在外部查询中使用表别名,则子查询中的别名将优先。

例:

CREATE TABLE #T (A INT)
CREATE TABLE #U (A INT)
CREATE TABLE #V (A INT)

INSERT INTO #T (A) VALUES (1), (2), (3)
INSERT INTO #U (A) VALUES (2), (3), (4)
INSERT INTO #V (A) VALUES (3), (4), (5)

SELECT
    T1.A
FROM
    #T AS T1
    INNER JOIN #U AS T2 ON T1.A = T2.A
WHERE
    EXISTS (SELECT * FROM #V AS T2 WHERE T1.A = T2.A)

输出为“ 3”:表T和U共有2和3,但是WHERE谓词进一步过滤返回到3的行,并且V中不存在2。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.