Los alias de las subconsultas son iguales a los alias de las consultas principales

23

Tengo una consulta SQL cuyos alias son los mismos que algunos de sus alias de subconsulta.

Por ejemplo:

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

Esto funciona bien, ya que el alias de la subconsulta parece ocultar el principal.

  1. ¿Funcionará de esa manera en todos los casos?
  2. ¿Alguna vez obtendré resultados indefinidos?
  3. Si está bien hacer eso, ¿cómo puedo hacer una referencia a la consulta principal r?
IcySnow
fuente
1
Las respuestas cortas son "1.Sí", "2.No" y "3.en ese caso, no puede (por lo que no está realmente bien si desea hacer esa referencia)"
ypercubeᵀᴹ

Respuestas:

15

Está bien que las subconsultas anidadas utilicen los mismos alias que se usan en la consulta principal, aunque puede ser un poco confuso para alguien que lee el código. El espacio de nombre para los alias en una subconsulta anidada es independiente del espacio de nombre en el padre. Por ejemplo, la consulta a continuación tiene una subconsulta anidada bque también tiene un alias butilizado. Esto sería potencialmente confuso para el programador, pero está bien con el motor 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

En una subconsulta correlacionada, tiene acceso a los alias principales, por lo que los alias deben ser únicos en la consulta principal y la subconsulta correlacionada. Si tomamos una subconsulta correlacionada como la siguiente, tenemos un espacio de nombre global único compartido entre la consulta principal y la subconsulta correlacionada:

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)

La subconsulta correlacionada no tiene un alias ya que no participa en una unión como tal 1 . Las referencias by b2for barestán disponibles para la subconsulta ya que las subconsultas correlacionadas comparten su espacio de nombres para los alias con el padre.


1 Tenga en cuenta que el optimizador puede elegir usar operadores de unión dentro del plan detrás de escena, aunque la operación real especificada es una subconsulta correlacionada y no una unión contra una subconsulta anidada.

Preocupado por TunbridgeWells
fuente
La subconsulta en la primera consulta es una tabla derivada y el SQL estándar requiere que siempre se le dé un nombre: no hay una razón lógica para este requisito, pero SQL Server lo ha implementado de todos modos, aunque en el ejemplo particular que ha elegido un nombre es realmente necesario. La subconsulta en la segunda consulta no es una tabla derivada, de ahí que no requiera un nombre (el hecho de que sea una subconsulta correlacionada es irrelevante).
cuando el
@onedaywhen: no puedo pensar en otra situación que no sea una subconsulta correlacionada donde la subconsulta necesita acceso a los alias utilizados en el padre. ¿Tenías algo específico en mente?
Preocupado por
No estoy seguro de entender tu pregunta. Quizás debería dejar en claro que estaba respondiendo específicamente a su comentario: "La subconsulta correlacionada no tiene un alias, ya que no participa en una unión como tal". Se suponía que mi respuesta transmitía el punto de que las reglas con respecto a las variables de rango (lo que el estándar SQL llama 'nombres de correlación' y usted llama 'alias') no están directamente relacionadas con su participación (o de otro modo) en las uniones.
cuando el
Ejemplo simple: SELECT * FROM ( SELECT c FROM T ) AS T2;- sin combinaciones, sin correlación, sin embargo, el estándar SQL requiere que a la tabla derivada se le asigne una variable de rango ( T2en este caso).
cuando el
3

ConcernedOfTunbridgeWells, usted escribe (el énfasis es mío): "En una subconsulta correlacionada tiene acceso a los alias principales, por lo que los alias deben ser únicos en la consulta principal y la subconsulta correlacionada".

No creo que se requiera singularidad. Creo que, si se usa un alias en una subconsulta correlacionada como nombre de correlación, así como un alias de tabla en la consulta externa, el alias en la subconsulta tendrá prioridad.

Ejemplo:

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)

El resultado es "3": las tablas T y U tienen 2 y 3 en común, pero el WHEREpredicado filtra aún más las filas devueltas a 3, y 2 no existe en V.

Slachterman
fuente