CodeGym /Kurse /SQL SELF /Verschachtelte Schleifen und Rekursion

Verschachtelte Schleifen und Rekursion

SQL SELF
Level 51 , Lektion 3
Verfügbar

Verschachtelte Schleifen sind Schleifen, die innerhalb anderer Schleifen laufen. Stell dir eine Interview-Fragerunde vor, bei der eine Frage zu weiteren Nachfragen führt. Die Logik von verschachtelten Schleifen ist: Die äußere Schleife macht eine Iteration, und die innere Schleife läuft für jede Iteration der äußeren Schleife durch.

Beispiel: Einmaleins-Tabelle

Wir schreiben eine Funktion, die eine Einmaleins-Tabelle für die Zahlen von 1 bis 5 erstellt. Das ist ein klassisches Beispiel für verschachtelte Schleifen:

CREATE OR REPLACE FUNCTION generate_multiplication_table()
RETURNS VOID AS $$
BEGIN
  FOR i IN 1..5 LOOP -- Äußere Schleife
    FOR j IN 1..5 LOOP -- Innere Schleife
      RAISE NOTICE '% x % = %', i, j, i * j; -- Ergebnis loggen
    END LOOP;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Funktionsaufruf:
SELECT generate_multiplication_table();

So funktioniert's:

  1. Die äußere Schleife nimmt die Werte i von 1 bis 5.
  2. Für jeden Wert von i nimmt die innere Schleife die Werte j von 1 bis 5.
  3. Bei jedem Schritt werden i und j kombiniert, um das Ergebnis der Multiplikation zu berechnen.
  4. Die Ausgabe sieht wie eine Mini-Tabelle aus:
   1 x 1 = 1
   1 x 2 = 2
   ...
   5 x 5 = 25

Praxis: Schnittmengen in zwei Tabellen finden

Jetzt machen wir ein etwas "realistischeres" Beispiel. Stell dir vor, wir haben zwei Tabellen:

  • students (Studenten, ihre Namen),
  • courses (Kurse, für die sie eingeschrieben sind).

Wir wollen Studenten finden, die in mehr als einem Kurs eingeschrieben sind. Wir nutzen verschachtelte Schleifen:

CREATE OR REPLACE FUNCTION find_students_with_multiple_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
  FOR student IN SELECT DISTINCT student_name FROM students LOOP
    FOR course IN SELECT DISTINCT course_name FROM courses WHERE student_id = student.student_id LOOP
      RETURN QUERY SELECT student.student_name, course.course_name;
    END LOOP;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Funktionsaufruf:
SELECT * FROM find_students_with_multiple_courses();

Rekursion

Rekursion bedeutet, dass eine Funktion sich selbst aufruft. Das ist so, als würdest du einen Kumpel bitten, SQL zu erklären, und er sagt: Lies die Doku, die wiederum auf diese Lektion verweist… Verwechsele Rekursion nicht mit einer Endlosschleife. Bei Rekursion gibt es immer eine "Abbruchbedingung" (der Punkt, an dem die Funktion aufhört, sich selbst aufzurufen).

Beispiel: Fakultät einer Zahl berechnen

Die Fakultät einer Zahl n ist das Produkt aller Zahlen von 1 bis n. Zum Beispiel ist die Fakultät von 5 (geschrieben als 5!) 5 * 4 * 3 * 2 * 1 = 120. So kann man das mit Rekursion umsetzen:

CREATE OR REPLACE FUNCTION calculate_factorial(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
  -- Abbruchbedingung: Fakultät von 0 oder 1 ist 1
  IF n = 0 OR n = 1 THEN
    RETURN 1;
  END IF;

  -- Rekursiver Funktionsaufruf
  RETURN n * calculate_factorial(n - 1);
END;
$$ LANGUAGE plpgsql;

-- Funktionsaufruf:
SELECT calculate_factorial(5); -- Ergebnis: 120

So funktioniert's:

  1. Wenn n 0 oder 1 ist, wird 1 zurückgegeben.
  2. Wenn n > 1, ruft die Funktion sich selbst mit dem Argument n - 1 auf und multipliziert das Ergebnis mit n.
  3. So "stapeln" sich die Aufrufe und werden dann in eine Richtung aufgelöst.

Praktisches Beispiel: Fibonacci-Zahlen

Fibonacci-Zahlen sind eine Zahlenfolge, bei der jede Zahl die Summe der beiden vorherigen ist. Die Folge beginnt so: 0, 1, 1, 2, 3, 5, 8....

Schreiben wir eine Funktion, die die n-te Zahl der Folge berechnet:

CREATE OR REPLACE FUNCTION fibonacci(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
  -- Abbruchbedingung: Die ersten zwei Zahlen sind bekannt
  IF n = 0 THEN
    RETURN 0;
  ELSIF n = 1 THEN
    RETURN 1;
  END IF;

  -- Rekursiver Funktionsaufruf
  RETURN fibonacci(n - 1) + fibonacci(n - 2);
END;
$$ LANGUAGE plpgsql;

-- Funktionsaufruf:
SELECT fibonacci(6); -- Ergebnis: 8

Wann sollte man verschachtelte Schleifen und Rekursion verwenden?

  1. Verschachtelte Schleifen sind super für Tabellenarbeit:

    • Vergleiche von Werten zwischen zwei Tabellen.
    • Komplexe Datenkombinationen bauen.
  2. Rekursion ist besser für:

    • Berechnung von Folgen (z.B. Fakultäten, Fibonacci).
    • Arbeiten mit hierarchischen Strukturen (z.B. Kategoriebaum für Produkte).

Typische Fehler

Verschachtelte Schleifen sind manchmal echte Performance-Killer, besonders bei großen Tabellen. Nutze sie nur, wenn du das Ergebnis nicht mit normalen SQL-Mitteln bekommst.

Bei Rekursion musst du unbedingt eine klare "Abbruchbedingung" haben. Sonst bekommst du einen endlosen Funktionsaufruf und wahrscheinlich einen Stack Overflow.

Komplexe verschachtelte Konstrukte können das Debugging erschweren. Hilf dir mit RAISE NOTICE, um Zwischenergebnisse auszugeben.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION