CodeGym /Corsi /SQL SELF /Cicli annidati e ricorsione

Cicli annidati e ricorsione

SQL SELF
Livello 51, Lezione 3
Disponibile

I cicli annidati sono cicli che girano dentro altri cicli. Immagina una sezione di domande a un colloquio, dove una domanda porta a nuove domande di approfondimento. La logica dei cicli annidati è questa: il ciclo esterno fa un giro, e il ciclo interno fa i suoi giri per ogni iterazione del ciclo esterno.

Esempio: tabella di moltiplicazione

Scriviamo una funzione che crea una tabella di moltiplicazione per i numeri da 1 a 5. È un esempio classico dove si usano i cicli annidati:

CREATE OR REPLACE FUNCTION generate_multiplication_table()
RETURNS VOID AS $$
BEGIN
  FOR i IN 1..5 LOOP -- Ciclo esterno
    FOR j IN 1..5 LOOP -- Ciclo interno
      RAISE NOTICE '% x % = %', i, j, i * j; -- Logghiamo il risultato
    END LOOP;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Chiamata della funzione:
SELECT generate_multiplication_table();

Logica di funzionamento:

  1. Il ciclo esterno prende i valori di i da 1 a 5.
  2. Per ogni valore di i, il ciclo interno prende i valori di j da 1 a 5.
  3. Ad ogni passo si combinano i valori di i e j per calcolare il risultato della moltiplicazione.
  4. L’output sembra una mini-tabella:
   1 x 1 = 1
   1 x 2 = 2
   ...
   5 x 5 = 25

Pratica: trovare le intersezioni tra due tabelle

Ora facciamo un esempio più “reale”. Immagina di avere due tabelle:

  • students (studenti, i loro nomi),
  • courses (corsi a cui sono iscritti).

Vogliamo trovare gli studenti iscritti a più di un corso. Usiamo i cicli annidati:

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;

-- Chiamata della funzione:
SELECT * FROM find_students_with_multiple_courses();

Ricorsione

La ricorsione è quando una funzione chiama se stessa. È come se chiedessi a un amico di spiegarti SQL e lui ti dicesse di leggere la documentazione che rimanda a questa stessa lezione… Non confondere la ricorsione con un ciclo infinito. La ricorsione ha sempre una “condizione di stop” (il punto in cui la funzione smette di chiamare se stessa).

Esempio: calcolo del fattoriale di un numero

Il fattoriale di un numero n è il prodotto di tutti i numeri da 1 a n. Per esempio, il fattoriale di 5 (si scrive 5!) è 5 * 4 * 3 * 2 * 1 = 120. Ecco come si può fare con la ricorsione:

CREATE OR REPLACE FUNCTION calculate_factorial(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
  -- Condizione di stop: il fattoriale di 0 o 1 è 1
  IF n = 0 OR n = 1 THEN
    RETURN 1;
  END IF;

  -- Chiamata ricorsiva della funzione
  RETURN n * calculate_factorial(n - 1);
END;
$$ LANGUAGE plpgsql;

-- Chiamata della funzione:
SELECT calculate_factorial(5); -- Risultato: 120

Logica di funzionamento:

  1. Se n è 0 o 1, ritorna 1.
  2. Se n > 1, la funzione chiama se stessa con n - 1 e moltiplica il risultato per n.
  3. Così le chiamate si “accumulano” e poi si risolvono tutte in una direzione.

Esempio pratico: numeri di Fibonacci

I numeri di Fibonacci sono una sequenza in cui ogni numero è la somma dei due precedenti. La sequenza inizia così: 0, 1, 1, 2, 3, 5, 8....

Scriviamo una funzione per calcolare l’n-esimo numero della sequenza:

CREATE OR REPLACE FUNCTION fibonacci(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
  -- Condizione di stop: i primi due numeri sono noti
  IF n = 0 THEN
    RETURN 0;
  ELSIF n = 1 THEN
    RETURN 1;
  END IF;

  -- Chiamata ricorsiva della funzione
  RETURN fibonacci(n - 1) + fibonacci(n - 2);
END;
$$ LANGUAGE plpgsql;

-- Chiamata della funzione:
SELECT fibonacci(6); -- Risultato: 8

Quando usare cicli annidati e ricorsione?

  1. I cicli annidati sono ottimi per lavorare con le tabelle:

    • Confrontare valori tra due tabelle.
    • Costruire combinazioni di dati complesse.
  2. La ricorsione è meglio per:

    • Calcolare sequenze (tipo fattoriali, Fibonacci).
    • Lavorare con strutture gerarchiche (tipo un albero di categorie di prodotti).

Errori tipici

I cicli annidati a volte sono “costosi” in termini di performance, soprattutto con tabelle grandi. Usali solo quando non puoi ottenere il risultato con i normali strumenti SQL.

Quando usi la ricorsione, assicurati di avere una “condizione di stop” chiara. Senza di essa avrai chiamate infinite e probabilmente un errore di stack overflow.

Costruzioni annidate complesse possono rendere il debug difficile. Aiutati con RAISE NOTICE per stampare risultati intermedi.

2
Compito
SQL SELF, livello 51, lezione 3
Bloccato
Tabellina semplice con cicli annidati
Tabellina semplice con cicli annidati
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION