Abfragen einer Common Table Expression (CTE) mittels FROM
Ein allgemeiner Tabellenausdruck – oder CTE – ist eine komplexere Variante der abgeleiteten Tabelle, aber auch leistungsfähiger.Eine Präambel, die mit dem Schlüsselwort WITH
beginnt, definiert eine oder mehrere benannte CTEs, jede mit einer optionalen Spalten-Alias-Liste.Die Hauptabfrage, die der Präambel folgt, kann dann auf diese CTEs zugreifen, als wären es reguläre Tabellen oder Ansichten.Die CTEs verlassen den Gültigkeitsbereich, sobald die Hauptabfrage vollständig ausgeführt wurde.
Eine vollständige Diskussion der CTEs finden Sie im Abschnitt [fblangref40-dml-select-cte-de].
Das Folgende ist eine Umschreibung unseres abgeleiteten Tabellenbeispiels als CTE:
with vars (b, D, denom) as (
select b, b*b - 4*a*c, 2*a from coeffs
)
select
iif (D >= 0, (-b - sqrt(D)) / denom, null) sol_1,
iif (D > 0, (-b + sqrt(D)) / denom, null) sol_2
from vars
Abgesehen davon, dass die Berechnungen, die zuerst durchgeführt werden müssen, jetzt am Anfang stehen, ist dies keine große Verbesserung gegenüber der abgeleiteten Tabellenversion.Allerdings können wir jetzt auch die doppelte Berechnung von sqrt(D)
für jede Zeile eliminieren:
with vars (b, D, denom) as (
select b, b*b - 4*a*c, 2*a from coeffs
),
vars2 (b, D, denom, sqrtD) as (
select b, D, denom, iif (D >= 0, sqrt(D), null) from vars
)
select
iif (D >= 0, (-b - sqrtD) / denom, null) sol_1,
iif (D > 0, (-b + sqrtD) / denom, null) sol_2
from vars2
Der Code ist jetzt etwas komplizierter, kann aber effizienter ausgeführt werden (je nachdem, was länger dauert: Ausführen der SQRT
-Funktion oder Übergabe der Werte von b
, D
und denom
durch einen zusätzlichen CTE) .Übrigens hätten wir das auch mit abgeleiteten Tabellen machen können, aber das würde eine Verschachtelung erfordern.
Important
|
Alle Spalten im CTE werden so oft ausgewertet, wie sie in der Hauptabfrage angegeben sind.Dies ist wichtig, da es bei der Verwendung nichtdeterministischer Funktionen zu unerwarteten Ergebnissen führen kann.Das Folgende zeigt ein Beispiel dafür.
Das Ergebnis, wenn diese Abfrage drei verschiedene Werte erzeugt: C1 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C2 C1214CD3-423C-406D-B5BD-95BF432ED3E3 C3 EB176C10-F754-4689-8B84-64B666381154 Um ein einzelnes Ergebnis der Funktion
Diese Abfrage erzeugt ein einzelnes Ergebnis für alle drei Spalten: C1 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C2 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C3 80AAECED-65CD-4C2F-90AB-5D548C3C7279 Eine alternative Lösung besteht darin, die Abfrage 'GEN_UUID' in eine Unterabfrage einzuschließen:
Dies ist ein Artefakt der aktuellen Implementierung.Dieses Verhalten kann sich in einer zukünftigen Firebird-Version ändern. |