Eine Unterabfrage kann nun eine Spalte aus der umgebenden Abfrage verwenden.
Damit steht eine übliche Methode zur Verfügung, um „die Zeile, die zu dieser Zeile gehört“ in Invantive UniversalSQL zu beschreiben, wie im untenstehenden Beispiel gezeigt. Bisher führte eine solche Unterabfrage zu einer Meldung, dass die Spalte unbekannt war.
Funktionsweise
Eine Unterabfrage sucht einen Namen zunächst in ihren eigenen Datenquellen. Erst wenn sie den Namen dort nicht kennt, schaut sie in die umgebende Abfrage und danach in die Abfrage, die diese wiederum umgibt. Ein Name, der an beiden Stellen existiert, verweist also auf den nächstgelegenen. Das Hinzufügen einer Spalte zu einer Tabelle kann daher nicht die Bedeutung einer bestehenden Unterabfrage verändern.
Eine Korrelation darf auf beliebig viele Ebenen nach außen greifen und kann eine Ebene überspringen. Eine Unterabfrage, die zwei Ebenen tief liegt, kann eine Spalte aus der äußeren Abfrage verwenden, ohne dass die dazwischenliegende Abfrage eine Rolle spielt.
Die Korrelation ist in denselben Formen erlaubt wie eine Unterabfrage ohne Korrelation: exists und not exists, in und not in, sowie die skalare Unterabfrage. Letztere liefert einen Wert und darf überall dort stehen, wo ein Ausdruck erlaubt ist, also auch in der Auswahlliste, in einer Berechnung und in einem case.
Beispiel: Existiert eine Zugehörige Zeile
Das folgende Beispiel wählt die Mitarbeiter aus, deren Abteilung in der zweiten Datensammlung vorkommt. Die Unterabfrage verwendet emp.dept, eine Spalte der umgebenden Abfrage:
select emp.code
from ( select 'A100' code, 'SLS' dept
union all
select 'A200' code, 'ENG' dept
) emp
where exists ( select 1
from ( select 'SLS' dept
) dpt
where dpt.dept = emp.dept
)
Dies liefert eine Zeile mit dem Wert A100. Mitarbeiter A200 arbeitet in einer Abteilung, die in der zweiten Sammlung nicht bekannt ist.
Beispiel: Ein Wert Pro Zeile
Eine skalare Unterabfrage in der Auswahlliste zählt die Zeilen, die zu jedem Mitarbeiter gehören:
select emp.code
, ( select count(*)
from ( select 'A100' code
union all
select 'A100' code
) ord
where ord.code = emp.code
) orders
from ( select 'A100' code
union all
select 'A200' code
) emp
Dies liefert A100 mit 2 und A200 mit 0. Eine count über keine zugehörigen Zeilen ergibt Null. Jede andere Aggregation, wie max oder sum, liefert in dieser Situation den leeren Wert.
Leere Werte
Ein Vergleich mit dem leeren Wert hat kein Ergebnis, und dieses Ergebnis variiert je nach Form. Bei exists ist eine Zeile, die mit dem leeren Wert verglichen wird, kein Treffer, sodass die Unterabfrage nichts findet. Bei not in macht ein leerer Wert zwischen den gelieferten Werten die Antwort unentschieden, wodurch die Zeile nicht geliefert wird. Das gilt auch, wenn der verglichene Wert selbst leer ist.
Anzahl der Anfragen an die Plattform
Eine korrelierte Unterabfrage wird vor der Ausführung in einen Join umgeschrieben. Jede Datenquelle wird dadurch unabhängig von der Anzahl der Zeilen der umgebenden Abfrage eine feste Anzahl von Malen gelesen.
Ohne diese Umschreibung würde die Unterabfrage einmal pro Zeile ausgeführt, was auf einer Plattform, die über die Cloud angesprochen wird, 1 Anfrage pro Zeile bedeutet.
Einschränkung
Eine Unterabfrage in einem order by wird noch nicht unterstützt.
Verfügbarkeit
Korrelierte Unterabfragen sind ab der Version 27.0 für alle Plattformen verfügbar.
