Rekurzivní SQL

  • Upload
    amal

  • View
    63

  • Download
    1

Embed Size (px)

DESCRIPTION

Rekurzivní SQL. Petr Čermák Michal Danihelka. Osnova. Úvod do problematiky Rekurzivní SQL v Oraclu Řešení rekurzivních úloh bez podpory rekurzivního SQL Rekurzivní SQL v DB/2 Použití DB/2 UDF. Úvod do problematiky. Co je to rekurzivní dotaz?. - PowerPoint PPT Presentation

Citation preview

  • Rekurzivn SQLPetr ermkMichal Danihelka

  • Osnovavod do problematikyRekurzivn SQL v Oraclueen rekurzivnch loh bez podpory rekurzivnho SQLRekurzivn SQL v DB/2Pouit DB/2 UDF

  • vod do problematiky

  • Co je to rekurzivn dotaz?Dotaz je rekurzivn, pokud se zznamy odkazuj sami na sebe pomoc primrnho nebo cizho kle.Vazba me bt pm, nebo i pes nkolik tabulek

  • Pouit rekurzivnch dotazObecn kdekoliv maj data hierarchickou strukturu

    Uspodn organizaceStruktura vrobkuRodinn hierarchie

  • Divergentn hierarchieKad uzel m nejve jednoho otceReprezentace tabulkou s poli Kl, Otec a njak hodnota piazen objektuKoen mono oznait napklad Kl = Otec

  • Konvergentn hierarchieUzel me mt vc pedk, nesm vak bt svm otcem / dttem (acyklick graf)Jedna tabulka nestaPotebujeme dv Objekty(PKey, Num) a Vztahy(PKey, CKey, Parametr vztahu)

  • Rekurzivn hierarchieGraf me obsahovat i cyklyReprezentace stejn jako v pedchozm ppaduRiziko zacyklen

  • Dal dlenVyvenHladiny vtinou rznch typBvaj divergentnNevyvenHladiny prvk stejnho druhu

  • Podpora rekurze v SQLANSI SQL nepodporuje dotazovn popsanm zpsobem ani vpoet obecn rekurzivnch funkcpodpora je zahrnuta v chystanm ANSI SQL3 (SQL:1999)nznaky implementace v ORACLE a DB2

  • Vlastnosti rekurzivnch dotazve na jeden dotaznepehlednostvhodn pouze kdy vyuiji velkou st vsledkov sady

  • Jak se obejt bez rekurze?Pouit cursor, cykl, ...Ztrta monosti optimalizaceKd nen tak elegantn

  • Poadavky kladen na rekurziPi prochzen grafem meme zskat:dosaitelnostvyslitelnost cestspojovn cest

    vpoet obecn rekurzivn funkce pi prchodu vrcholem nebo hranou

  • Pklad: (vztahy mezi soustmi)P1P2P3P4P5P6P7P8P9222211233

  • DosaitelnostZ danho vrcholu, nebo mnoiny vrchol, chceme zjistit vechny dosaiteln potomkyZ jakch st se skld vrobek P1?

  • Vyslitelnost cestZobraz celou strukturu vrobku P1 se vemi jeho stmi

    P1(1)P2(2)P3(2)P4(2)P5(6)P6(4)P7(6)P8(8)P9(4)222211233P6(2)P8(4)P9(4)12

  • Spojovn cestJak jsou sti vrobku P1 a kolik jich je teba k jeho sestaven?

    P1(1)P2(2)P3(2)P4(2)P5(6)P6(6)P7(6)P8(12)P9(6)222211233

  • Rekurzivn SQL v Oraclu

  • Co Oracle podporuje?dosaitelnostvyslitelnost cestjednu rekurzivn funkci level

  • Pklad: (struktura vrobku)CREATE TABLE Parts(part# CHAR(5) PRIMARY KEY, part_name CHAR(4) NOT NULL, assembly_time INTEGER NOT NULL CHECK (VALUE >= 0), category_id INTEGER NOT NULL, FOREIGN KEY category_id REFERENCES Category);

    CREATE TABLE Usage(parent_part# CHAR(5) NOT NULL, component_part# CHAR(5) NOT NULL, quantity INTEGER NOT NULL, PRIMARY KEY(parent_part#, component_part#), FOREIGN KEY parent_part# REFERENCES Parts, FOREIGN KEY component_part# REFERENCES Parts);

  • CONNECT BY, START WITHKlauzule START WITHdefinuje poten podmnku pro dotaz

    CONNECT BYspecifikuje vazbu mezi rodiovskmi dky a potomky (pomoc opertoru PRIOR)

  • Pklad: (zobraz strukturu vrobku vyslitelnost cest)SELECT LEVEL, parent_part#, component_part#FROM UsageCONNECT BY PRIOR component_part# = parent_part#START WITH parent_part# = P1

    Vsledek dotazu nen tabulka, vsledek je nutn uspodanOmezen -- nemonost potat libovolnou obecn rekurzivn funkciomezen na pouvn spojen v rek. dotazech

  • Algoritmus zpracovn dotazu1) Zjisti dky splujc podmnku v START WITH2) Najdi vechny potomky vzhledem k dkm z kroku 2 nebo pedchozho kroku 3 splujc podmnku v CONNECT BY3) Opakuj krok 3 dokud dostv nov dky4)Eliminuj vechny dky, kter nespluj podmnku ve WHERE5) Vra zbyl dky.

  • Poad vrcench dkdky jsou vraceny v preorderu tj. nejdve rodiovsk vrchol, pak teprve podstromy.

  • Pklad: (Dosaitelnost)SELECT DISTINCT component_part#FROM (viz. select pro zobrazen struktury)

  • Pklad: (obchzen joinu v connect by soustky s popisem)SELECT part#, category_name FROM Parts,CategoryWHERE Parts.category_id = Category.category_id AND part# IN (SELECT component_part#FROM UsageSTART WITH parent_part# = P1CONNECT BY PRIOR componet_part# = parent_part#);

  • Pklad: (obchzen joinu v connect by dosaiteln dvojice)SELECT DISTINCT PX.part#, PX.part_name#, PY.part#, PY.part_name# FROM Parts PX,Parts PYWHERE PY.part# IN (SELECT component_part#FROM UsageSTART WITH parent_part# = PX.part#CONNECT BY PRIOR componet_part# = parent_part#)ORDER BY PX.part#, PY.part#;

  • Rozen Oracle 9i podpora joinSELECT employee_name, manager_name, dept_name FROM employee, dept WHERE employee.deptno = dept.deptno START WITH employee_name = 'KING' CONNECT BY PRIOR employee_id = manager_id;

  • Rozen Oracle 9i tdn dk s danm pedkem SELECT employee_name, manager_name, dept_name FROM employee, dept WHERE employee.deptno = dept.deptno START WITH employee_name = 'KING' CONNECT BY PRIOR employee_id = manager_id ORDER SIBLINGS BY hire_date;

  • Rozen Oracle 9i - cestySELECT employee_name, SYS_CONNECT_BY_PATH(employee_name, '/') "PATH" FROM employee START WITH employee_name = 'KING' CONNECT BY PRIOR employee_id = manager_id;

  • Rozen Oracle 10g spolen pedek SELECT DISTINCT CONNECT_BY_ROOT assembly_id, CONNECT_BY_ROOT assembly_name FROM bill_of_materials WHERE part_number = 1019 START WITH parent_assembly IS NULL CONNECT BY parent_assembly = PRIOR assembly_id; CONNECT_BY_ROOTASSEMBLY_ID CONNECT_BY_ROOTASSEMBLY 100 Automobile

  • Rozen Oracle 10g jsem list? st 1SELECT ASSEMBLY_ID, RPAD(' ', 2*(LEVEL-1)) || assembly_name assembly_name, quantity, CONNECT_BY_ISLEAFFROM bill_of_materials WHERE LEVEL
  • Rozen Oracle 10g jsem list? st 2SELECT ASSEMBLY_ID, RPAD(' ', 2*(LEVEL-1)) || assembly_name assembly_name, quantity, CONNECT_BY_ISLEAF FROM bill_of_materials WHERE LEVEL = 2 START WITH assembly_id = 110 CONNECT BY parent_assembly = PRIOR assembly_id;

  • Rozen Oracle 10g cyklySELECT RPAD(' ', 2*(LEVEL-1)) || assembly_name assembly_name, quantity, CONNECT_BY_ISCYCLE FROM bill_of_materials START WITH assembly_id = 100CONNECT BY NOCYCLE parent_assembly = PRIOR assembly_id;

  • een rekurzivnch loh bez podpory rekurzivnho SQL

  • Formty pro tabulky jakoto vsledky dotaz st 1Na rozdl od oracla nesmj mt tyto tabulky dn slovn, aby li pouvat v poddotazechFormt dostupnosti (kam se vude dostanu z vrcholu) sta binrn tabulka obsahujc koen a syna

  • Formty pro tabulky jakoto vsledky dotaz st 2Formt vyslovn cest (struktura s potem podst) pouijeme nsledujc tabulku Formt spojovn cest (seznam nslednk s potem) pouijeme nsledujc tabulku

  • Kterak pout ANSI SQL k vyhodnocen rekurzivnch dotaz st 1Dostupnost SELECT DISTINCT parent_part#, component_part# FROM PartsPathEnum WHERE parent_part# = P1

    Vyslovn cest SELECT * FROM PartsPathEnum WHERE parent_part# = P1 ORDER BY squence#;

  • Kterak pout ANSI SQL k vyhodnocen rekurzivnch dotaz st 2Spojovn cestSELECT parent_part#, component_part#, SUM(total_quantity)FROM PartsPathEnumWHERE parent_part# = P1GROUP BY parent_part#,component_part#;

  • Kde vzt tabulku vyslitelnosti cest?PL/SQL nebo jakkoliv jazyk podporujc rekurzi a SQLDoporueno udlat index na kombinaci sloupc (parent_part#,component_part#), jeliko je tato tabulka typicky hodn velikNen aktuln, ale v praxi vtinou nevad

  • Oezvn dotazuSELECT PE1.*FROM PartsPathEnum PE1, PartsPathEnum PE2WHERE PE1.parent_part# = P1 AND PE2.parent_part# = P1 AND PE2.component_part# = P3AND (PE1.seq# NOT BETWEEN PE2.seq# AND PE2.max_subtree_seq#)ORDER BY PE1.seq#;

  • Rekurzivn SQL v DB/2

  • vodn pkladkol: Zskat seznam potomk (i nepmch) uzlu A. HIERARCHYABCDEFG

    PKEYCKEYNUMAB1AC5AD20CE33DE44DF5FG5

  • eenWITH PARENT (PKEY, CKEY) AS(SELECT PKEY, CKEY FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.PKEY, C.CKEY FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY)SELECT PKEY, CKEYFROM PARENT;ABCDEFG

  • een problmu zacyklenTk se rekurzivnch hierarchiDv zkladn metody een:Zastavit prochzen po uritm potu hladinUdrovat si seznam navtvench uzl a ignorovat dve navtven

  • Pklad 2Seznam potomk s hloubkou, v jak se nalzaj.WITH PARENT (CKEY, LVL) AS(SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY)SELECT PKEY, CKEYFROM PARENT;ABCDEFG

    CKEYLVLA0B1C1D1E2E2F2G3

  • Pklad 3Seznam potomk hloubky max. 2WITH PARENT (CKEY, LVL) AS(SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY)SELECT PKEY, CKEYFROM PARENT,WHERE LVL < 3;ABCDEFG

    CKEYLVLA0B1C1D1E2E2F2

  • Pklad 3 podruhSeznam potomk hloubky max. 2WITH PARENT (CKEY, LVL) AS(SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND P.LVL + 1 < 3)SELECT PKEY, CKEYFROM PARENT;ABCDEFG

    CKEYLVLA0B1C1D1E2E2F2

  • Pklad 4Vpis cesty, kter m dlku 4WITH TEMP1 (CKEY, LVL) AS(SELECT DISTINCT PKEY, 1 FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, TEMP1 P WHERE P.CKEY = C.PKEY AND P.LVL < 4),ABCDEFGTEMP2 (CKEY, LVL) AS(SELECT CKEY, LVL FROM TEMP1, WHERE LVL = 4 UNION ALL SELECT C.PKEY, D.LVL 1 FROM HIERARCHY C, TEMP2 D WHERE D.CKEY = C.CKEY)SELECT * FROM TEMP2;

    CKEYLVLG4F3D2A1

  • Pklad 5Vichni potomci uzlu A do 4. hladinyHIERARCHYABCDEFG

    PKEYCKEYABACADCEDADEDFFG

  • Pklad 5 - eenABCDEFGWITH PARENT (CKEY, LVL) AS(SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND P.LVL + 1 < 4)SELECT PKEY, CKEYFROM PARENT;

    CKEYLVLA0B1C1D1E2A2E2F2B3C3D3G3

  • Pklad 5 lep eenABCDEFGWITH PARENT (CKEY, LVL) AS(SELECT DISTINCT PKEY, 0 FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1 FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND P.LVL + 1 < 4),NO_DUPS (CKEY, LVL, NUM) AS(SELECT CKEY, MIN(LVL), COUNT(*) FROM PARENT GROUP BY CKEY)SELECT CKEY, LVL, NUM FROM NO_DUPS;

    CKEYLVLNUMA02B12C12D12E22F21G31

  • Pklad 6Udrovn seznamu navtvench uzlABCDEFGWITH PARENT (CKEY, LVL, PATH) AS(SELECT DISTINCT PKEY, 0, VARCHAR(PKEY, 20) FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT C.CKEY, P.LVL + 1, P.PATH || > || C.CKEY FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY AND LOCATE(C.CKEY || >, P.PATH) = 0)SELECT CKEY, LVL, PATH FROM PARENT;

    CKEYLVLPATHA0AB1A>BC1A>CD1A>DE2A>C>EE2A>D>EF2A>D>FG3A>D>F>G

  • Definice tabulky pro p. 6CREATE TABLE HIERARCHY(PKEY CHAR(3) NOT NULL, CKEY CHAR(3) NOT NULL, CONSTRAINT TBX1 PRIMARY KEY (PKEY, CKEY), CONSTRAINT TBC1 CHECK (PKEY CKEY), CONSTRAINT TBC2 CHECK (LOCATE(>, PKEY) = 0), CONSTRAINT TBC3 CHECK (LOCATE(>, CKEY) = 0));CREATE UNIQUE INDEX TBLE_X1 ON HIERARCHY (CKEY, PKEY);

  • Pklad 7 Detekce cyklABCDEFGWITH PARENT (CKEY, LVL, PATH) AS(SELECT DISTINCT PKEY, VARCHAR(PKEY, 20) FROM HIERARCHY WHERE PKEY = A UNION ALL SELECT CASE WHEN LOCATE(C.CKEY || >, P.PATH) > 0 THEN RAISE_ERROR(70001, CHYBA: Graf obsahuje cyklus); ELSE C.CKEY END, P.PATH || > || C.CKEY FROM HIERARCHY C, PARENT P WHERE P.CKEY = C.PKEY)SELECT CKEY, PATH FROM PARENT;

  • P. 8 - Tvorba syntetickch datVe spojen s INSERTCREATE TABLE NUMBERS(COUNTER INTEGER, RANDOM INTEGER)INSERT INTO NUMBERS(COUNTER, RANDOM) WITH TEMP(N) AS (VALUES (1) UNION ALL SELECT N + 1 FROM TEMP WHERE N < 1000 ) SELECT N, INTEGER(RAND() * 1000) FROM TEMP;

  • Rekurze s potnmKomponenty kdla letadla:KdloPkaKidlkoPodvozekPantNt5101005284311

  • Pklad 9Poet ntWITH WINGPARTS(SUBPART, QTY) AS(SELECT SUBPART, QTY FROM COMPONENTS WHERE PART = Kdlo UNION ALL SELECT C.SUBPART, P.QTY * C.QTY FROM WINGPARTS P, COMPONENTS C WHERE P.SUBPART = C.PART)SELECT SUBPART, SUM(QTY) AS QTYFROM WINGPARTSWHERE SUBPART = Nt;COMPONENTS

    PARTSUBPARTQTYKdloPka5KdloKidlko1KdloPodvozek1KdloNt100PkaNt10KidlkoPant2KidlkoNt5PodvozekPant3PodvozekNt8PantNt4

  • Pklad 9 - Vsledek

    SUBPARTQTYPka5Kidlko1Podvozek1Nt100Nt50Pant2Nt5Pant3Nt8Nt8Nt12

  • Pouit DB/2 UDF

  • Kde rek. SQL DB/2 nestaProblm: Nelze pst korelovan rekurzivn poddotazy rekurzivnch dotazPklad korelovanho poddotazu:SELECT POSSIBLE.ENAME, POSSIBLE.DEPT, POSSIBLE.SALARY FROM EMPLOYEE POSSIBLE WHERE SALARY > (SELECT AVG (SALARY) FROM EMPLOYEE AVERAGE WHERE POSSIBLE.DEPT = AVERAGE.DEPT);

  • Pklad 10SportyHobbyProf.FotbalBasketUivatelSkupina ASkupina BSkupina B1FrantaKarel

    Dokument 1Dokument 2Dokument 3

  • Pklad 10 - dotazPotebujeme zjistit, na jak dokumenty ze stromu sport m uivatel Karel pstup a ke kterm pedmtm nle.Musme rozvinout hierarchii sport pro zskn dokument a pro kad dokument z hierarchie prv zjistit, zda na nj m Karel prvo.een - UDF

  • Pklad 10 datov modelitem_idparent_iditem_namegrpsubgrpgrpnamedocument_idnameTabulky: Subject, Group, Document, Subject_Document, Group_DocumentSubjectGroupDocumentitem_idparent_iddocument_idgrpsubgrpdocument_idSubject_DocumentGroup_Document

  • Pklad 10 - StrategieRozvineme hierarchii sport -> zskme dokumenty (vnj rekurzivn dotaz)*Pro kad dokument z hierarchie sport rozvineme skupiny uivatel a zjistme, zda se v nich nachz Karel (UDF s parametry ID dokumentu a uivatel)SELECT za * na kad vrcen dokument zavol zmnnou UDF

  • Pklad 10 - UDF CREATE FUNCTION ISELIGIBLE (Doc Integer, Uname character (64)) RETURNS INTEGER LANGUAGE SQL READS SQL DATA NO EXTERNAL ACTION NOT DETERMINISTIC RETURN WITH Main (subgrp, grpname) AS (SELECT subgrp, grpname FROM Group WHERE (subgrp) IN (SELECT subgrp FROM Group_Document WHERE document_id=Doc ) UNION ALL SELECT C.subgrp, C.grpname FROM Group C, Main M WHERE M.subgrp = C.grp ) SELECT COUNT(*) FROM main WHERE Ucase(grpname)=Ucase(Uname)

  • Pklad 10 Vsledn dotazWITH Rpl (parent_id, item_id, item_name) AS (SELECT ROOT.parent_id, ROOT.item_id, ROOT.item_name FROM SubjectROOT WHERE ROOT.parent_id = 1 UNION ALL SELECT CHILD.parent_id, CHILD.item_id, CHILD.item_name FROM RPL PARENT, Subject CHILD WHERE PARENT.item_id = CHILD.parent_id ) SELECT DISTINCT Rpl.parent_id, Rpl.item_id, Rpl.item_name, document.document_id, document.name, ISELIGIBLE(document.document_id, char('Karel')) eligible FROM (Rpl JOIN Subject_Document sd ON Rpl.item_id = sd.item_id ) JOIN document ON document.document_id = sd.document_id;

    klic = otec dobre pred uvedenim rekurzivniho sql, nebot bylo mozno rozvinout hierarchii pomoci joinu. Michal (??)... u rekurze riziko zacykleniNapriklad geograficke objekty... staty, kraje, okresy, mesta..2 tabulky kdyz chceme u objektu mit vic info.. jinak by to tam bylo vickratS tou jsme delali na zacatku..Problem: A->B, A->C, B->D, C->D, kolik deti ma A?treba hierarchie ve firmach...Zminit hierarchii s ukazately? (jde predevsim o strukturu)vs. data nutno provadet i vypocty...With definuje tzv. Common table expression. Tabulka, kter trva pouze po dobu dotazu. Nepotrebuje vlastn tablespace.. (to samy jako select * from a as (select ...), b where a...Select, nebo Select All, select distinct nen povolen.. Stejne jako pouze union allTypy sloupecku jsou urceny prvnim podselektem, kter nesmi byt rekurzivni (jinak zmna pomoci CAST)Rekurzivni dotaz nesmi obsahovat zadne group by, having.., nesmi obsahovat poddotaz odkazujici se na parent.Distinct u toho nerekurzivniho selectu nevadi.Po kliknuti se zobrazi tabulka.Vsichni vidi, ze to je osklivy...Tohle uz je lepsi,nejenze je to efektivnejsi (neprohledava to celou hierarchii),ale taky zabranuje zacykleni.Takto lze definovat vic temp. pohledu najednou... takhle lze projit treba vic hierarchii v jednom dotazu...neni povoleno cyklicke volani.. tzn aby se temp1 odkazovala na temp2 a naopak.

    Pri ruznych dotazech varovani, ze se muze zacyklit...Pribyl radek D ACREATE TABLE HIERARCHY(PKEY CHAR(03) NOT NULL, CKEY CHAR(03) NOT NULL, CONSTRAINT TBX1 PRIMARY KEY (PKEY, CKEY), CONSTRAINT TBC1 CHECK (PKEY CKEY), CONSTRAINT TBC2 CHECK (LOCATE(>, PKEY) = 0), CONSTRAINT TBC3 CHECK (LOCATE(>, CKEY) = 0));CREATE UNIQUE INDEX TBLE_X1 ON HIERARCHY (CKEY, PKEY);INSERT INTO HIERARCHY VALUES (.., ..), (....Tohle uz tam jednou bylo...(to s tim PKEY ziska to spravnej typ, chyba, kdyz to tam nebude)Nevyhody musime mit odhad na lvl, dostali se nam tam duplikaty, navis s ruznymi hladinami...Treba takhle bychom chteli spocitat hladinu..Pouzity dve temporarni tabulka, aby se no_dups dalo jeste pripojit k jinym.Typy sloupecku jsou urceny prvnim selektem. Naalokovat radeji velke, varchatr stejne zabira jen co potrebujeZde se tvori cesta z korene do uzlu, ktery je prave prochazen. Viz. sloupec pathZabraneni vybrani jiz navstiveneho uzlu. (Tohle neuvazuje smycky) LOCATE vrati pozici podretezce, 0, kdyz se tam nevyskytuje. Vyuziva to toho, ze klic je definovan tak, ze nesmi obsahovat znak >, viz Je to efektivnejsi, nez orezavani dle lvl, protoze to do nekonecnych cyklu vubec nevleze.TBC1 Zabrani smyckamTBC2, 3 Zabrani vyskytu > v klicich.Pokud mame klice ciselne, staci na ne pouzit funkci CHARDriv, nez vleze do cyklu, vyhodi chybuGraf vyjadrujici, kolik ktera cast potrebuje komponent jineho typuZde je priklad, proc muze rekurze potrebovat duplicity.Kliknuti vysledek...No..a pak uz staci bud select sum, where, nebo pokud chceme vsechny dily, tak GROUP BY SUBPART, SUM(QTY)Jmeno, oddeleni, plat lib. zamestnance, ktery ma plat vyssi, nez prumer v jeho oddeleniVyhodnoceni poddotazu zavisi na zpracovavanem radku vnejsiho dotazu.Neboli...je to poddotaz, kterej je spusten pro kazdou radku vnejsiho dotazu...Je to vlastne poruseni podminky acyklicnosti zavislosti mezi common table expressions.(?)user defined functions.. .driv v Java / C, ted uz i SQLDekompozice m:nPokud tam neni, je tam 0Prohlizi se smerem od group obsahujicich dokument DOLU. (smerem k uzivatelum)Predpokladame, ze Sport ma ID 1(pokud tam maj bejt i ty druhyPK, tak tam prijde za ON jeste AND Rpl.parent_id = sd.parent_id