init at work
This commit is contained in:
Executable
+549
@@ -0,0 +1,549 @@
|
||||
#datenbank
|
||||
Kontext: Datenbanken
|
||||
|
||||
= ==Common Table Expression==
|
||||
|
||||
>`WITH`-Block in SQL-Abfrage
|
||||
|
||||
➡️[[#Zusammenfassung]]
|
||||
|
||||
---
|
||||
Im Folgenden bekommst du eine umfassende, aber einsteigerfreundliche Einführung in CTEs („Common Table Expressions“) im Kontext von Datenbanken – mit Definition, Abgrenzung, Nutzen, Herausforderungen und praxisnahen Beispielen.
|
||||
|
||||
---
|
||||
|
||||
## 1. Grundidee: Was ist eine CTE?
|
||||
|
||||
**CTE** steht für **Common Table Expression**.
|
||||
Vereinfacht gesagt ist eine CTE:
|
||||
|
||||
> Eine **temporäre, benannte Ergebnismenge**, die du in einer SQL-Abfrage definierst und im Anschluss in derselben Abfrage wie eine Tabelle verwenden kannst.
|
||||
|
||||
Man kann sich das vorstellen wie:
|
||||
|
||||
- „Ich speichere mir ein Zwischenergebnis unter einem Namen…“
|
||||
- „…und benutze dieses Zwischenergebnis dann in der eigentlichen Anfrage.“
|
||||
|
||||
Grundform:
|
||||
|
||||
```sql
|
||||
WITH name_der_cte AS (
|
||||
-- irgendeine SELECT-Abfrage
|
||||
SELECT ...
|
||||
FROM ...
|
||||
WHERE ...
|
||||
)
|
||||
SELECT *
|
||||
FROM name_der_cte;
|
||||
```
|
||||
|
||||
Wichtig:
|
||||
|
||||
- Die CTE existiert **nur für diese eine Abfrage**.
|
||||
- Sie wird **innerhalb der Abfrage** definiert und direkt **danach** genutzt.
|
||||
- Man kann CTEs **mehrfach referenzieren**, als wären es echte Tabellen.
|
||||
|
||||
---
|
||||
|
||||
## 2. Ein einfaches Beispiel
|
||||
|
||||
Stell dir vor, du hast eine Tabelle `bestellungen`:
|
||||
|
||||
- `id`
|
||||
- `kunde_id`
|
||||
- `betrag`
|
||||
- `datum`
|
||||
|
||||
Du möchtest:
|
||||
|
||||
1. Alle Bestellungen des Jahres 2024 herausfiltern.
|
||||
2. Dann auf Basis dieser gefilterten Daten den Gesamtumsatz pro Kunde berechnen.
|
||||
|
||||
Ohne CTE könnte man das mit einer verschachtelten Abfrage lösen; mit CTE sieht es lesbarer aus:
|
||||
|
||||
```sql
|
||||
WITH bestellungen_2024 AS (
|
||||
SELECT *
|
||||
FROM bestellungen
|
||||
WHERE datum >= '2024-01-01'
|
||||
AND datum < '2025-01-01'
|
||||
)
|
||||
SELECT
|
||||
kunde_id,
|
||||
SUM(betrag) AS umsatz_2024
|
||||
FROM bestellungen_2024
|
||||
GROUP BY kunde_id;
|
||||
```
|
||||
|
||||
Die CTE `bestellungen_2024` ist hier:
|
||||
„Alle Bestellungen aus 2024“, und wird anschließend in der Hauptabfrage verwendet.
|
||||
|
||||
---
|
||||
|
||||
## 3. Abgrenzung zu ähnlichen oder verwandten Begriffen
|
||||
|
||||
### 3.1 CTE vs. Unterabfrage (Subquery / Derived Table)
|
||||
|
||||
**Unterabfrage**: Eine Abfrage innerhalb einer anderen Abfrage, z. B.:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
kunde_id,
|
||||
SUM(betrag) AS umsatz_2024
|
||||
FROM (
|
||||
SELECT *
|
||||
FROM bestellungen
|
||||
WHERE datum >= '2024-01-01'
|
||||
AND datum < '2025-01-01'
|
||||
) AS b2024
|
||||
GROUP BY kunde_id;
|
||||
```
|
||||
|
||||
Unterschiede:
|
||||
|
||||
- **CTE**: Wird am Anfang mit `WITH` definiert, trägt einen Namen und kann **mehrfach** benutzt werden.
|
||||
- **Subquery**: Steht direkt im `FROM` oder `WHERE`, ist meist **anonymer** und schwerer zu lesen, vor allem bei komplexen Konstrukten.
|
||||
|
||||
Funktional können CTEs und Subqueries oft das Gleiche – CTEs verbessern eher **Struktur und Lesbarkeit**.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 CTE vs. View (Sicht)
|
||||
|
||||
**View** (Sicht) ist wie eine **gespeicherte Abfrage** in der Datenbank:
|
||||
|
||||
```sql
|
||||
CREATE VIEW bestellungen_2024 AS
|
||||
SELECT *
|
||||
FROM bestellungen
|
||||
WHERE datum >= '2024-01-01'
|
||||
AND datum < '2025-01-01';
|
||||
```
|
||||
|
||||
Dann kannst du schreiben:
|
||||
|
||||
```sql
|
||||
SELECT kunde_id, SUM(betrag)
|
||||
FROM bestellungen_2024
|
||||
GROUP BY kunde_id;
|
||||
```
|
||||
|
||||
Unterschiede:
|
||||
|
||||
- **View**:
|
||||
- Wird **dauerhaft** in der Datenbank definiert.
|
||||
- Hat einen Namen, kann von **vielen Abfragen** und auch anderen Nutzer:innen verwendet werden.
|
||||
- Ändert sich nur über `CREATE OR REPLACE VIEW` / `ALTER VIEW`.
|
||||
- **CTE**:
|
||||
- Gilt **nur für eine einzige Abfrage**.
|
||||
- Ist daher ideal für **einmalige** oder **sehr spezialisierte** Zwischenschritte.
|
||||
- Erfordert keine Rechte zum Erstellen von Objekten in der Datenbank (kein `CREATE VIEW`).
|
||||
|
||||
Kurz:
|
||||
Views = dauerhafte, wiederverwendbare Bausteine.
|
||||
CTEs = temporäre, einmalige Bausteine innerhalb einer Abfrage.
|
||||
|
||||
---
|
||||
|
||||
### 3.3 CTE vs. temporäre Tabelle
|
||||
|
||||
Viele Datenbanken kennen **temporäre Tabellen**, z. B. `#temp_tab` in SQL Server oder `CREATE TEMP TABLE` in PostgreSQL:
|
||||
|
||||
```sql
|
||||
CREATE TEMP TABLE bestellungen_2024 AS
|
||||
SELECT *
|
||||
FROM bestellungen
|
||||
WHERE datum >= '2024-01-01'
|
||||
AND datum < '2025-01-01';
|
||||
|
||||
SELECT kunde_id, SUM(betrag)
|
||||
FROM bestellungen_2024
|
||||
GROUP BY kunde_id;
|
||||
```
|
||||
|
||||
Unterschiede:
|
||||
|
||||
- **Temporäre Tabelle**:
|
||||
- Wird physisch (zumindest logisch) in der Datenbank angelegt.
|
||||
- Existiert für die Dauer einer Session oder Transaktion.
|
||||
- Kann **indiziert** werden (Index hinzufügen) und so bei großen Datenmengen Performancevorteile bringen.
|
||||
- **CTE**:
|
||||
- Keine echte Tabelle, eher eine „logische Abfragekomponente“.
|
||||
- Keine eigenen Indexe.
|
||||
- Gilt nur innerhalb einer Abfrage.
|
||||
|
||||
---
|
||||
|
||||
### 3.4 CTE vs. Stored Procedure / Function
|
||||
|
||||
**Stored Procedures** und **Functions** sind Programmierbausteine auf Datenbankseite, z. B.:
|
||||
|
||||
- Prozeduren: führen mehrere Schritte, ggf. mit Kontrollstrukturen aus (IF, WHILE,…).
|
||||
- Funktionen: geben einen Wert oder eine Tabelle zurück.
|
||||
|
||||
Unterschiede:
|
||||
|
||||
- CTE ist **Teil einer einzelnen SQL-Select/Insert/Update/Delete-Abfrage**.
|
||||
- Stored Proc / Function ist **Code**, den man **speichert, versioniert und immer wieder aufrufen** kann.
|
||||
|
||||
CTEs können innerhalb von Stored Procedures verwendet werden – sie sind eher Bausteine **auf Abfrage-Ebene**, nicht auf Programm-Ebene.
|
||||
|
||||
---
|
||||
|
||||
## 4. Welche Probleme werden durch CTEs gelöst?
|
||||
|
||||
### 4.1 Bessere Lesbarkeit und Struktur
|
||||
|
||||
Statt eine riesige, komplexe Abfrage mit vielen verschachtelten Unterabfragen zu schreiben, kann man sich die Abfrage in **logische Schritte** zerlegen:
|
||||
|
||||
1. `WITH schritt1 AS (...)`
|
||||
2. `, schritt2 AS (...)`
|
||||
3. `SELECT ... FROM schritt2 ...`
|
||||
|
||||
Beispiel:
|
||||
Du möchtest erst „aktive Kunden“ bestimmen und dann nur deren Bestellungen summieren:
|
||||
|
||||
```sql
|
||||
WITH aktive_kunden AS (
|
||||
SELECT id, name
|
||||
FROM kunden
|
||||
WHERE status = 'aktiv'
|
||||
),
|
||||
bestellungen_aktive_kunden AS (
|
||||
SELECT
|
||||
b.kunde_id,
|
||||
SUM(b.betrag) AS umsatz
|
||||
FROM bestellungen b
|
||||
JOIN aktive_kunden k ON k.id = b.kunde_id
|
||||
GROUP BY b.kunde_id
|
||||
)
|
||||
SELECT
|
||||
k.name,
|
||||
bak.umsatz
|
||||
FROM bestellungen_aktive_kunden bak
|
||||
JOIN aktive_kunden k ON k.id = bak.kunde_id;
|
||||
```
|
||||
|
||||
Jeder CTE beschreibt einen **klaren Teilschritt**, das erleichtert Verstehen und Warten des Codes.
|
||||
|
||||
---
|
||||
|
||||
### 4.2 Wiederverwendung innerhalb einer Abfrage
|
||||
|
||||
Oft brauchst du ein bestimmtes Zwischenergebnis **mehrmals in derselben Abfrage**.
|
||||
Ohne CTE müsstest du:
|
||||
|
||||
- Dieselbe Unterabfrage mehrfach schreiben (redundant, fehleranfällig)
|
||||
- Oder du machst Temp-Tabellen / Views, die aber mehr Setup erfordern.
|
||||
|
||||
Mit CTE definierst du das einmal und verwendest es mehrfach:
|
||||
|
||||
```sql
|
||||
WITH bestellungen_2024 AS (
|
||||
SELECT *
|
||||
FROM bestellungen
|
||||
WHERE datum >= '2024-01-01'
|
||||
AND datum < '2025-01-01'
|
||||
)
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM bestellungen_2024) AS anzahl_gesamt,
|
||||
(SELECT SUM(betrag) FROM bestellungen_2024) AS umsatz_gesamt;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Schrittweise Transformationen (ETL-artige Abläufe)
|
||||
|
||||
Man kann komplexe Datenverarbeitungen in **mehrere CTE-Schritte** aufteilen, z. B.:
|
||||
|
||||
1. Rohdaten bereinigen (ungültige Werte rausfiltern)
|
||||
2. Daten anreichern (Join mit Lookup-Tabellen)
|
||||
3. Aggregationen berechnen
|
||||
4. Ergebnis selektieren
|
||||
|
||||
Schema:
|
||||
|
||||
```sql
|
||||
WITH raw_data AS (
|
||||
SELECT * FROM import_tabelle
|
||||
),
|
||||
cleaned_data AS (
|
||||
SELECT *
|
||||
FROM raw_data
|
||||
WHERE wert IS NOT NULL
|
||||
),
|
||||
enriched_data AS (
|
||||
SELECT
|
||||
c.*,
|
||||
l.beschreibung
|
||||
FROM cleaned_data c
|
||||
LEFT JOIN lookup l ON c.code = l.code
|
||||
),
|
||||
aggregated AS (
|
||||
SELECT
|
||||
beschreibung,
|
||||
COUNT(*) AS anzahl,
|
||||
AVG(wert) AS durchschnitt
|
||||
FROM enriched_data
|
||||
GROUP BY beschreibung
|
||||
)
|
||||
SELECT *
|
||||
FROM aggregated
|
||||
ORDER BY anzahl DESC;
|
||||
```
|
||||
|
||||
Solche „linearen“ CTE-Ketten sind sehr hilfreich, um komplexe ETL-Schritte innerhalb einer SQL-Abfrage klar zu definieren.
|
||||
|
||||
---
|
||||
|
||||
### 4.4 Rekursive Abfragen (Hierarchien, Bäume, Graphen)
|
||||
|
||||
Ein **besonderer Typ** von CTE ist die **rekursive CTE**. Damit kann man Strukturen abfragen, die **hierarchisch** sind, z. B.:
|
||||
|
||||
- Mitarbeiter und ihre Vorgesetzten (Organigramm)
|
||||
- Kategorien und Unterkategorien (Baumstrukturen)
|
||||
- Stücklisten (Bauteil besteht aus Unterteilen, die wiederum Unterteile haben)
|
||||
- Graphen/Netzwerke mit Verbindungen
|
||||
|
||||
Grundidee:
|
||||
|
||||
- Es gibt eine **Anker-Abfrage** (Startpunkt).
|
||||
- Und eine **rekursive Abfrage**, die sich immer wieder selbst referenziert.
|
||||
|
||||
Beispiel: Mitarbeiter-Hierarchie
|
||||
Tabelle `mitarbeiter`:
|
||||
|
||||
- `id`
|
||||
- `name`
|
||||
- `chef_id` (Verweis auf `id` in derselben Tabelle, NULL für Chef ganz oben)
|
||||
|
||||
```sql
|
||||
WITH RECURSIVE hierarchie AS (
|
||||
-- 1) Anker: Chef (oberste Ebene)
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
chef_id,
|
||||
0 AS ebene
|
||||
FROM mitarbeiter
|
||||
WHERE chef_id IS NULL
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2) Rekursiver Teil: alle Mitarbeiter, die einem bereits gefundenen Mitarbeiter unterstellt sind
|
||||
SELECT
|
||||
m.id,
|
||||
m.name,
|
||||
m.chef_id,
|
||||
h.ebene + 1 AS ebene
|
||||
FROM mitarbeiter m
|
||||
JOIN hierarchie h ON m.chef_id = h.id
|
||||
)
|
||||
SELECT *
|
||||
FROM hierarchie
|
||||
ORDER BY ebene, id;
|
||||
```
|
||||
|
||||
Ergebnis:
|
||||
Alle Mitarbeiter mit einer Spalte `ebene`, die angibt, wie weit sie vom obersten Chef entfernt sind.
|
||||
|
||||
**Ohne rekursive CTEs** wäre das sehr umständlich oder gar nicht (standardkonform) direkt in SQL möglich. Manche Systeme haben dafür eigene Syntax (z. B. `CONNECT BY` in Oracle), rekursive CTEs sind der **SQL-Standard**-Weg.
|
||||
|
||||
---
|
||||
|
||||
## 5. Weitere praxisnahe Beispiele
|
||||
|
||||
### 5.1 Alltagsszenario: „Top-Produkte pro Monat“
|
||||
|
||||
Gegeben:
|
||||
|
||||
- `verkaeufe` mit Spalten:
|
||||
- `produkt_id`
|
||||
- `datum`
|
||||
- `menge`
|
||||
- `umsatz`
|
||||
|
||||
Ziel:
|
||||
Pro Monat die **Top 3 Produkte nach Umsatz** anzeigen.
|
||||
|
||||
Ein möglicher Weg mit CTE:
|
||||
|
||||
```sql
|
||||
WITH monatliche_umsaetze AS (
|
||||
SELECT
|
||||
DATE_TRUNC('month', datum) AS monat,
|
||||
produkt_id,
|
||||
SUM(umsatz) AS umsatz_monat
|
||||
FROM verkaeufe
|
||||
GROUP BY DATE_TRUNC('month', datum), produkt_id
|
||||
),
|
||||
ranking AS (
|
||||
SELECT
|
||||
monat,
|
||||
produkt_id,
|
||||
umsatz_monat,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY monat
|
||||
ORDER BY umsatz_monat DESC
|
||||
) AS rang_im_monat
|
||||
FROM monatliche_umsaetze
|
||||
)
|
||||
SELECT
|
||||
monat,
|
||||
produkt_id,
|
||||
umsatz_monat,
|
||||
rang_im_monat
|
||||
FROM ranking
|
||||
WHERE rang_im_monat <= 3
|
||||
ORDER BY monat, rang_im_monat;
|
||||
```
|
||||
|
||||
Die Logik wird nachvollziehbar in zwei Schritte aufgeteilt:
|
||||
|
||||
1. summieren pro Monat und Produkt
|
||||
2. pro Monat ranken und Top 3 auswählen
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Kalender-CTE: fehlende Tage auffüllen
|
||||
|
||||
Manchmal hat man z. B. nur Daten für Tage, an denen Verkäufe stattfanden, möchte aber **jeden Tag im Zeitraum** sehen (auch wenn Umsatz 0 ist).
|
||||
Mit einer rekursiven CTE kann man einen Kalender erzeugen.
|
||||
|
||||
Beispiel (PostgreSQL-Syntax):
|
||||
|
||||
```sql
|
||||
WITH RECURSIVE kalender AS (
|
||||
SELECT DATE '2024-01-01' AS tag
|
||||
UNION ALL
|
||||
SELECT tag + INTERVAL '1 day'
|
||||
FROM kalender
|
||||
WHERE tag < DATE '2024-01-31'
|
||||
)
|
||||
SELECT
|
||||
k.tag,
|
||||
COALESCE(SUM(v.umsatz), 0) AS umsatz
|
||||
FROM kalender k
|
||||
LEFT JOIN verkaeufe v ON DATE(v.datum) = k.tag
|
||||
GROUP BY k.tag
|
||||
ORDER BY k.tag;
|
||||
```
|
||||
|
||||
So erhältst du für **jeden Tag im Januar 2024** einen Umsatzwert – bei Tagen ohne Verkäufe eben 0.
|
||||
|
||||
---
|
||||
|
||||
## 6. Welche Herausforderungen und Stolpersteine gibt es?
|
||||
|
||||
### 6.1 Performance (Leistungsfähigkeit)
|
||||
|
||||
CTEs sind primär ein **Lesbarkeits-Feature**, aber sie können die Performance beeinflussen – je nach Datenbank:
|
||||
|
||||
- Einige Datenbanken „materialisieren“ CTEs:
|
||||
- Das Zwischenergebnis wird wirklich berechnet und zwischengespeichert.
|
||||
- Mehrfachzugriff ist dann ggf. schneller, aber die Initialberechnung kann teurer sein.
|
||||
- Andere optimieren CTEs ähnlich wie Unterabfragen:
|
||||
- Sie werden im Optimizer „eingefaltet“, d. h. wie eine direkte Teilabfrage behandelt.
|
||||
|
||||
Typische Punkte:
|
||||
|
||||
- **Mehrfache Verwendung großer CTEs**:
|
||||
- Wenn eine CTE sehr groß ist und du mehrfach darauf zugreifst, kann das teuer werden.
|
||||
- In manchen Systemen ist dann eine temporäre Tabelle mit Index effizienter.
|
||||
- **Rekursive CTEs**:
|
||||
- Können viel CPU und Zeit brauchen, wenn die Hierarchie sehr tief oder stark verzweigt ist.
|
||||
- Es gibt oft eine maximale Rekursionstiefe (z. B. 100 oder 32767), die begrenzt, wie tief die Rekursion geht.
|
||||
|
||||
Praxis-Tipp:
|
||||
|
||||
- CTEs sind super für mittlere Komplexität und moderate Datenmengen.
|
||||
- Bei sehr großen Datenmengen und Performanceproblemen:
|
||||
- Ausführungsplan anschauen.
|
||||
- Mit Temp-Tabellen, Indizes oder Views experimentieren.
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Übermäßige Verschachtelung
|
||||
|
||||
Wenn man CTEs zu exzessiv nutzt, z. B. 20 oder mehr CTEs in einer Abfrage, wird es:
|
||||
|
||||
- schwer zu lesen
|
||||
- schwierig zu debuggen
|
||||
- komplex zu warten
|
||||
|
||||
Hier gilt:
|
||||
**Abstraktion, wo sinnvoll, aber nicht übertreiben.**
|
||||
|
||||
Manchmal ist es besser:
|
||||
|
||||
- Teile der Logik in eine View zu legen,
|
||||
- oder in eine Stored Procedure / Function,
|
||||
- oder die Logik in mehrere kleinere Abfragen aufzuteilen.
|
||||
|
||||
---
|
||||
|
||||
### 6.3 Datenbankspezifische Unterschiede
|
||||
|
||||
Nicht jede Datenbank:
|
||||
|
||||
- unterstützt CTEs gleich
|
||||
- oder hat genau dieselbe Syntax.
|
||||
|
||||
Beispiele:
|
||||
|
||||
- **PostgreSQL**: Unterstützt `WITH` und `WITH RECURSIVE`.
|
||||
- **SQL Server**: Unterstützt CTEs, Rekursion ohne extra `RECURSIVE`-Keyword.
|
||||
- **MySQL**: Ab Version 8.0 gibt es CTEs, rekursiv mit `WITH RECURSIVE`.
|
||||
- **Oracle**: Unterstützt CTEs, hatte aber historisch eigene Hierarchie-Syntax (`CONNECT BY`).
|
||||
|
||||
Wenn du in mehreren Systemen arbeitest, lohnt ein Blick in die Dokumentation der jeweiligen Datenbank.
|
||||
|
||||
---
|
||||
|
||||
### 6.4 CTEs haben keine eigenen Indizes
|
||||
|
||||
Da CTEs keine physischen Tabellen sind, kannst du:
|
||||
|
||||
- keine Indexe darauf erstellen
|
||||
- keine Statistiken direkt auf CTE-Ebene pflegen
|
||||
|
||||
D. h.:
|
||||
|
||||
- Der Optimizer muss die Abfrage so gut wie möglich auf Grundlage der zugrundeliegenden Tabellen optimieren.
|
||||
- Bei Performanceproblemen kann eine echte (temporäre) Tabelle mit Index manchmal besser sein.
|
||||
|
||||
---
|
||||
|
||||
## 7. Wann sollte man CTEs einsetzen? – Orientierung
|
||||
|
||||
**Geeignet für CTEs:**
|
||||
|
||||
- Wenn eine Abfrage **schwer lesbar** ist, weil sie viele Unterabfragen enthält.
|
||||
- Wenn du **dasselbe Zwischenergebnis mehrfach** in einer Abfrage benötigst.
|
||||
- Wenn du **schrittweise Transformationen** ausdrücken möchtest („Step 1, Step 2, …“).
|
||||
- Wenn du **Hierarchien** oder rekursive Strukturen mit SQL abbilden willst.
|
||||
|
||||
**Eher nicht ideal:**
|
||||
|
||||
- Für dauerhafte, von vielen Personen genutzte Logik → eher **Views** oder **Stored Procedures**.
|
||||
- Für sehr große Zwischenergebnisse, die oft wiederverwendet werden → evtl. **temporäre Tabellen** mit Index.
|
||||
- Wenn Performance schon kritisch ist → CTE-Einsatz testen und Ausführungspläne prüfen.
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
- **Definition**: CTE = „Common Table Expression“ = eine **temporäre, benannte Ergebnismenge** innerhalb einer Abfrage, definiert mit `WITH`.
|
||||
- **Nutzen**:
|
||||
- Klarere Struktur und bessere Lesbarkeit komplexer SQL-Abfragen.
|
||||
- Wiederverwendbarkeit eines Zwischenergebnisses innerhalb derselben Abfrage.
|
||||
- Möglichkeit, komplexe Transformationen sequenziell auszudrücken.
|
||||
- Unterstützung rekursiver Abfragen (Hierarchien/Bäume).
|
||||
- **Abgrenzung**:
|
||||
- Gegenüber Subqueries: funktional ähnlich, aber meist lesbarer.
|
||||
- Gegenüber Views: CTEs sind **temporär**, Views **dauerhaft**.
|
||||
- Gegenüber Temp-Tabellen: CTEs sind logisch, Temp-Tabellen physisch und indexierbar.
|
||||
- **Herausforderungen**:
|
||||
- Performanceabhängig vom Datenbanksystem und vom Aufbau der Abfrage.
|
||||
- Übermäßiger Gebrauch kann Abfragen unübersichtlich machen.
|
||||
- Rekursive CTEs können komplex und teuer werden, brauchen sorgfältige Bedingungen.
|
||||
Reference in New Issue
Block a user