Aliasy zapytań takie same jak aliasy głównych zapytań

23

Mam zapytanie SQL, którego aliasy są takie same jak niektóre aliasy jego podzapytania.

Na przykład:

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

Działa to dobrze, ponieważ alias podzapytania wydaje się ukrywać główny.

  1. Czy to zadziała we wszystkich przypadkach?
  2. Czy kiedykolwiek uzyskam niezdefiniowane wyniki?
  3. Jeśli jest to w porządku, jak mogę odwoływać się do głównych zapytań r?
IcySnow
źródło
1
Krótkie odpowiedzi to „1.Tak”, „2.Nie” i „3. W takim przypadku nie możesz (więc naprawdę nie jest OK, jeśli chcesz zrobić takie odniesienie)”
ypercubeᵀᴹ

Odpowiedzi:

15

W zagnieżdżonych podkwerendach można używać tych samych aliasów, co w zapytaniu nadrzędnym, chociaż może to być nieco mylące dla osoby czytającej kod. Przestrzeń nazw dla aliasów w zagnieżdżonym podzapytaniu jest oddzielna od przestrzeni nazw w obiekcie nadrzędnym. Na przykład poniższe zapytanie zawiera zagnieżdżone podzapytanie, bktóre ma również bużywany alias . Byłoby to potencjalnie mylące dla programisty, ale w porządku z silnikiem 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

W skorelowanym podzapytaniu masz dostęp do aliasów rodzica, więc aliasy muszą być unikalne w zapytaniu nadrzędnym i skorelowanym podzapytaniu. Jeśli weźmiemy skorelowane podkwerendy, takie jak poniższe, mamy jedną globalną przestrzeń nazw współdzieloną między kwerendą nadrzędną a skorelowaną podkwerendą:

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)

Skorelowane podzapytanie nie ma aliasu, ponieważ nie uczestniczy w sprzężeniu jako takim 1 . Odnośniki bi b2for barsą dostępne dla podkwerendy, ponieważ skorelowane podkwerendy współużytkują swoją przestrzeń nazw dla aliasów z rodzicem.


1 Zauważ, że optymalizator może zdecydować się na użycie operatorów łączenia w planie za kulisami, chociaż rzeczywista określona operacja jest skorelowanym podzapytaniem, a nie złączeniem z podzapytaniem zagnieżdżonym.

ConcernedOfTunbridgeWells
źródło
Podkwerenda w pierwszym zapytaniu jest tabelą pochodną, ​​a standardowy SQL wymaga, aby zawsze nadawano jej nazwę: nie ma logicznego powodu dla tego wymagania, ale SQL Server i tak go zaimplementował, chociaż w konkretnym przykładzie, który wybrałeś, nazwa jest rzeczywiście wymagany. Podkwerenda w drugim zapytaniu nie jest tabelą pochodną, ​​dlatego nie wymaga nazwy (fakt, że jest to skorelowana kwerenda, jest nieistotny).
poniedziałek
@onedaywhen - Nie mogę wymyślić żadnej sytuacji poza skorelowanym podkwerendą, w której podkwerenda potrzebuje dostępu do aliasów używanych w elemencie nadrzędnym. Czy miałeś na myśli coś konkretnego?
ConcernedOfTunbridgeWells
Nie jestem pewien, czy rozumiem twoje pytanie. Być może powinienem wyjaśnić, że konkretnie odpowiadałem na twój komentarz: „Skorelowane podzapytanie nie ma aliasu, ponieważ nie uczestniczy w sprzężeniu jako takim”. Moja odpowiedź miała na celu wskazanie, że reguły dotyczące zmiennych zakresowych (co standard SQL nazywa „nazwami korelacji”, a ty nazywacie „aliasami”), nie są bezpośrednio związane z ich udziałem (lub w inny sposób) w złączeniach.
poniedziałek
Prosty przykład: SELECT * FROM ( SELECT c FROM T ) AS T2;- brak sprzężeń, brak korelacji, jednak standard SQL wymaga, aby tabeli pochodnej przypisano zmienną zakresu ( T2w tym przypadku).
poniedziałek
3

ConcernedOfTunbridgeWells piszesz (moje podkreślenie): „W skorelowanym podzapytaniu masz dostęp do aliasów rodzica, więc aliasy muszą być unikalne w zapytaniu nadrzędnym i skorelowanym podzapytaniu”.

Nie wierzę, że wyjątkowość jest wymagana. Uważam, że jeśli w skorelowanym podzapytaniu zostanie użyty alias jako nazwa korelacji, a także alias tabeli w zapytaniu zewnętrznym, pierwszeństwo będzie miał alias w podzapytaniu.

Przykład:

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)

Dane wyjściowe to „3”: tabele T i U mają wspólne 2 i 3, ale WHEREpredykat dodatkowo filtruje wiersze zwrócone do 3, a 2 nie istnieje w V.

slachterman
źródło