Rekurzió. Az Eljut-feladat. Tankönyv 10.2. Az Eljut-feladat. Rekurzió az SQL-ben
     Feladat:  
     -- Adott Jaratok(legitarsasag, honnan, hova, koltseg, indulas, erkezes) táblában
        repülőjáratok adatait tároljuk (honnan-hova várospárok). Azt keressük, hogy
        Dallasból mely városokba tudunk eljutni (közvetlenül vagy egy/több átszállással). 
     -- Ezzel a scripttel jaratok_tabla.txt készítsünk saját táblát, ami alapján dolgozunk.
     
>> (1) Eljut feladat  és megoldása SQL-1999 szabványban és Oracle-ben
>> (2) megoldása PL/SQL-ben  >>> megoldás ötletek >>> megoldás vázlata


     >> Tankönyv 11.2 fejezetében adott SQL-1999 szabvány megoldás (csak papíron!)
            WITH RECURSIVE eljut AS
                  (SELECT honnan, hova FROM jaratok
             UNION
                  SELECT eljut.honnan, jaratok.hova
                  FROM eljut, jaratok
                  WHERE eljut.hova = jaratok.honnan)
            SELECT hova FROM eljut WHERE honnan='DAL';
     -- Megj.: itt fontos: UNION (halmaz) és UNION ALL (multihalmaz) közötti különbség!

     >> A fenti csak egy kis változtatással fut le az Oracle-ben! Oracle 11gR2 megoldás:
            with eljut (honnan, hova) as
                   (select honnan, hova from jaratok
               union all
                    select jaratok.honnan, eljut.hova
                    from jaratok, eljut
                    where jaratok.hova=eljut.honnan
                    )
                SEARCH DEPTH FIRST BY honnan SET SORTING
                CYCLE honnan SET is_cycle TO 1 DEFAULT 0
            select distinct honnan, hova from eljut order by honnan;
   

     
    -- Az "Eljut feladat" megvalósítása PL/SQL-ben
       >> Ehhez hozzuk létre egy alábbi szerkezetű ELJUT táblát:
            DROP TABLE Eljut;
            CREATE TABLE Eljut(
                             honnan VARCHAR2(10),
                             hova VARCHAR2(10));

       -- Írjunk egy olyan PL/SQL programot, ami feltölti az ELJUT táblát a megfelelő
          város párokkal, ahol az első városból el lehet jutni a másodikba. Mely (x, y)
          várospárokra lehetséges egy vagy több átszállással eljutni x városból y városba?
     
Megoldás ötletek-1: 
-- Írjunk egy PL/SQL programot, amellyel az Eljut(honnan, hova) táblának a sorait
    a Járatok tábla és az Eljut tábla (eddigi) tartalma alapján töltsük fel: Ehhez ciklust
    kell szervezni, amelyben az insert utasítás több sor felvitelére alkalmas alakját
    használjuk: A Járatok és Eljut táblák lekérdezésének az eredményét vigyük fel.
   
Megoldás ötletek-2: 
-- Eljut tábla növelése (sorok felvitele) ciklusban. Mikor lépünk ki a ciklusból? Ehhez
   a ciklus során ellenőrizni kell, hogy növekszik-e a sorok száma (Régi/Új Számláló),
   és duplikátumokra is figyelni kell, egy honnan-hova várospár ne kerüljön be duplán!
   

   
Megoldás vázlata:
   DECLARE
    RegiSzamlalo INTEGER:= 0;
    UJSzamlalo INTEGER:= 0;
 
  BEGIN
 
-- A ciklus előtt kezdeti értékek beállítása (a járatok alapján honnan-hova várospárok)
   
  delete from eljut;
  RegiSzamlalo:= 0;
  insert into eljut
    (select distinct honnan, hova from jaratok);

  select count(*) into UjSzamlalo from eljut;

-- A ciklust addig kell végrehajtani, ameddig növekszik az eredmény, fontos,
-- hogy csak olyan várospárokat vegyünk az eredményhez, ami még nem volt!

  LOOP
  insert into eljut
    (select distinct eljut.honnan,jaratok.hova
     from eljut, jaratok  
     where eljut.hova = jaratok.honnan
     and (
eljut.honnan,jaratok.hova)
          NOT IN (select * from eljut)
);
  select count(*) into UjSzamlalo from eljut;
  EXIT WHEN UjSzamlalo = RegiSzamlalo;
  RegiSzamlalo := UjSzamlalo;
  END LOOP;
  END;
  /
   
     --  A fenti megoldásban  NOT IN alkérdéssel szűrtük ki, hogy egy várospár
         csak egyszer legyen az eredményben. Próbáljuk ki más megoldásokkal is,
         például NOT EXISTS alkérdéssel vagy a MINUS halmazművelettel illetve
         egyéb megoldásokkal! Hogyan tudjuk kizárni az azonos várospárokat?

   
     -- A program végrehajtása után ellenőrizzük le, kérdezzük le az eljut táblát:
             select * from eljut order by honnan, hova;