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;