Aliase für Unterabfragen wie Aliase für Hauptabfragen

22

Ich habe eine SQL-Abfrage, deren Aliase mit denen einiger Aliase der Unterabfrage übereinstimmen.

Beispielsweise:

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

Dies funktioniert einwandfrei, da der Alias ​​der Unterabfrage den Alias ​​der Hauptabfrage zu verbergen scheint.

  1. Funktioniert das auf alle Fälle so?
  2. Bekomme ich jemals undefinierte Ergebnisse?
  3. Wenn das in Ordnung ist, wie kann ich dann auf die Hauptabfrage verweisen r?
IcySnow
quelle
1
Kurze Antworten sind "1.Ja", "2.Nein" und "3.In diesem Fall können Sie nicht (es ist also nicht wirklich in Ordnung, wenn Sie eine solche Referenz
erstellen

Antworten:

15

Für verschachtelte Unterabfragen ist es in Ordnung, dieselben Aliase wie für die übergeordnete Abfrage zu verwenden, obwohl dies für jemanden, der den Code liest, etwas verwirrend sein kann. Der Namensraum für Aliase in einer verschachtelten Unterabfrage unterscheidet sich vom Namensraum auf dem übergeordneten Element. Die folgende Abfrage enthält beispielsweise eine verschachtelte Unterabfrage b, in der auch ein Alias bverwendet wird. Für den Programmierer ist dies möglicherweise verwirrend, für die DBMS-Engine jedoch in Ordnung:

   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

In einer korrelierten Unterabfrage haben Sie Zugriff auf die Aliase der übergeordneten Abfrage, sodass die Aliase in der übergeordneten Abfrage und in der korrelierten Unterabfrage eindeutig sein müssen. Wenn wir eine korrelierte Unterabfrage wie die folgende verwenden, haben wir einen einzigen globalen Namensraum, der von der übergeordneten Abfrage und der korrelierten Unterabfrage gemeinsam genutzt wird:

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)

Die korrelierte Unterabfrage hat keinen Alias, da sie nicht an einem Join als solchem ​​teilnimmt 1 . Die Referenzen bund b2für barstehen der Unterabfrage beide zur Verfügung, da korrelierte Unterabfragen ihren Namespace für Aliase mit dem übergeordneten Element teilen.


1 Beachten Sie, dass das Optimierungsprogramm im Hintergrund möglicherweise Verknüpfungsoperatoren im Plan verwendet, obwohl der angegebene Vorgang eine korrelierte Unterabfrage und keine Verknüpfung mit einer verschachtelten Unterabfrage ist.

Betroffen vonTunbridgeWells
quelle
Die Unterabfrage in der ersten Abfrage ist eine abgeleitete Tabelle, und Standard-SQL erfordert, dass ihr immer ein Name zugewiesen wird: Es gibt keinen logischen Grund für diese Anforderung, aber SQL Server hat sie trotzdem implementiert, obwohl Sie in dem bestimmten Beispiel tatsächlich einen Namen ausgewählt haben erforderlich. Die Unterabfrage in der zweiten Abfrage ist keine abgeleitete Tabelle, weshalb kein Name erforderlich ist (die Tatsache, dass es sich um eine korrelierte Unterabfrage handelt, spielt keine Rolle).
Eintägig, wenn der
@onedaywhen - Ich kann mir keine andere Situation vorstellen als eine korrelierte Unterabfrage, bei der die Unterabfrage Zugriff auf Aliase benötigt, die im übergeordneten Objekt verwendet werden. Hatten Sie etwas Bestimmtes im Sinn?
ConcernedOfTunbridgeWells
Ich bin mir nicht sicher, ob ich deine Frage verstehe. Vielleicht sollte ich klarstellen, dass ich speziell auf Ihren Kommentar reagiert habe: "Die korrelierte Unterabfrage hat keinen Alias, da sie nicht an einem Join als solchem ​​teilnimmt." Meine Antwort sollte verdeutlichen, dass die Regeln für Bereichsvariablen (wie der SQL-Standard Korrelationsnamen und Sie Aliase nennt) nicht in direktem Zusammenhang mit ihrer Teilnahme (oder auf andere Weise) an Joins stehen.
Onedaywhen
Einfaches Beispiel: SELECT * FROM ( SELECT c FROM T ) AS T2;- Keine Verknüpfungen, noch keine Korrelation Der SQL-Standard verlangt, dass der abgeleiteten Tabelle eine Bereichsvariable zugewiesen wird ( T2in diesem Fall).
Onedaywhen
3

ConcernedOfTunbridgeWells, schreiben Sie (Hervorhebung von mir): „Auf einer korrelierten Unterabfrage Sie Zugriff auf die Eltern - Aliase haben, so dass die Aliase müssen über die übergeordnete Abfrage und korrelierte Unterabfrage eindeutig sein.“

Ich glaube nicht, dass Einzigartigkeit erforderlich ist. Ich glaube, wenn ein Alias ​​in einer korrelierten Unterabfrage als Korrelationsname sowie ein Tabellenalias in der äußeren Abfrage verwendet wird, hat der Alias ​​in der Unterabfrage Vorrang.

Beispiel:

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)

Die Ausgabe ist "3": Tabellen T und U haben 2 und 3 gemeinsam, aber das WHEREPrädikat filtert die zu 3 zurückgegebenen Zeilen weiter und 2 ist in V nicht vorhanden.

Slachterman
quelle