Gli alias delle sottoquery sono uguali agli alias delle query principali


23

Ho una query SQL i cui alias sono gli stessi di alcuni alias della sua subquery.

Per esempio:

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

Funziona bene, dato che l'alias della subquery sembra nascondere quello principale.

  1. Funzionerà in questo modo in tutti i casi?
  2. Avrò mai risultati indefiniti?
  3. Se è corretto farlo, come posso fare un riferimento alla query principale r?

1
Le risposte brevi sono "1.Sì", "2.No" e "3.in quel caso, non puoi (quindi non è proprio OK se vuoi fare un riferimento del genere)"
ypercubeᵀᴹ

Risposte:


15

Va bene per le sottoquery nidificate utilizzare gli stessi alias utilizzati nella query principale, anche se potrebbe essere un po 'confuso per qualcuno che legge il codice. Lo spazio dei nomi per gli alias su una sottoquery nidificata è separato dallo spazio dei nomi sul genitore. Ad esempio, la query di seguito ha una sottoquery nidificata bche contiene anche un alias b. Ciò sarebbe potenzialmente fonte di confusione per il programmatore ma andrebbe bene con il motore 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

Su una sottoquery correlata hai accesso agli alias dei genitori, quindi gli alias devono essere univoci nella query padre e nella sottoquery correlata. Se prendiamo una sottoquery correlata come quella qui sotto abbiamo un unico spazio dei nomi globale condiviso tra la query principale e la sottoquery correlata:

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 sottoquery correlata non ha un alias in quanto non partecipa a un join in quanto tale 1 . I riferimenti be b2for barsono entrambi disponibili per la sottoquery poiché le sottoquery correlate condividono il loro spazio dei nomi per gli alias con il genitore.


1 Notare che l'ottimizzatore può scegliere di utilizzare gli operatori di join all'interno del piano dietro le quinte, sebbene l'operazione effettiva specificata sia una sottoquery correlata e non un'unione rispetto a una sottoquery nidificata.


La sottoquery nella prima query è una tabella derivata e SQL standard richiede che gli venga sempre assegnato un nome: non esiste alcun motivo logico per questo requisito, ma SQL Server lo ha implementato comunque, sebbene nell'esempio specifico che hai scelto un nome sia effettivamente necessario. La sottoquery nella seconda query non è una tabella derivata, quindi perché non richiede un nome (il fatto che sia una sottoquery correlata è irrilevante).
giorno

@onedaywhen - Non riesco a pensare ad alcuna situazione ma a una subquery correlata in cui la subquery necessita dell'accesso agli alias utilizzati nel genitore. Avevi in ​​mente qualcosa di specifico?
Preoccupato di

Non sono sicuro di aver capito la tua domanda. Forse dovrei chiarire che stavo rispondendo specificamente al tuo commento, "La sottoquery correlata non ha un alias in quanto non partecipa a un join in quanto tale". La mia risposta avrebbe dovuto far capire che le regole riguardanti le variabili di intervallo (ciò che lo standard SQL chiama "nomi di correlazione" e che chiamate "alias") non sono direttamente correlate alla loro partecipazione (o altrimenti) ai join.
giorno

Esempio semplice: SELECT * FROM ( SELECT c FROM T ) AS T2;- nessun join, nessuna correlazione, tuttavia lo standard SQL richiede che alla tabella derivata venga assegnata una variabile di intervallo ( T2in questo caso).
giorno

3

Preoccupato di TunbridgeWells, scrivi (sottolineatura mia): "Su una sottoquery correlata hai accesso agli alias dei genitori, quindi gli alias devono essere univoci tra la query padre e la sottoquery correlata."

Non credo sia richiesta l'unicità. Ritengo che, se un alias viene utilizzato in una sottoquery correlata come nome di correlazione, nonché un alias di tabella nella query esterna, l'alias nella sottoquery avrà la precedenza.

Esempio:

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)

L'output è "3": le tabelle T e U hanno 2 e 3 in comune, ma il WHEREpredicato filtra ulteriormente le righe restituite a 3 e 2 non esiste in V.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.