Cviceni 5
-- 1) Tabulka dual:
-- Syntaxe oraclu nedovoluje pouziti prikazu "select" bez klauzule "from"
-- (napr. MySQL neco takoveho povoluje). Prikaz "select 1+1" je syntakticky
-- nespravny. Chceme-li zapsat prikaz bez pristupu dat k tabulce muzeme uvest
-- tabulku dual, ke ktere mame automaticky pristup aniz bychom ji vytvareli.
SQL>  SELECT 1+1 FROM dual;

       1+1
----------
         2

SQL>  DESC dual;

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)


-- chyba: do tabulky dual nemame zapisova prava (je umistena v systemove databazi) 
SQL>  INSERT INTO dual VALUES ('A');

INSERT INTO dual VALUES ('A')
            *
ERROR at line 1:
ORA-01031: insufficient privileges

-- Tabulka dual neni v nasi databazi, takze pokud potrebujeme mit v nasi
-- databazi vlastni tabulku s nazvem dual nic nam v tom nebrani.
SQL>  CREATE TABLE dual (a number);
SQL>  INSERT INTO dual VALUES (1);
SQL>  SELECT * FROM dual;

         A
----------
         1

SQL>  DROP TABLE dual;


-- 2) Spojeni tabulek
-- Mame tabulku ucitelu, tabulku predmetu a tabulku kdo, co uci. Chceme
-- vypsat textove ktery ucitel uci ktery predmet:
SQL>  DROP TABLE ucitele;
SQL>  DROP TABLE predmety;
SQL>  DROP TABLE uci;

SQL>  CREATE TABLE ucitele (id NUMBER PRIMARY KEY, jmeno VARCHAR2(20));
SQL>  INSERT INTO ucitele VALUES (1,'Matyas');
SQL>  INSERT INTO ucitele VALUES (2,'Riha');
SQL>  INSERT INTO ucitele VALUES (3,'Svenda');

SQL>  CREATE TABLE predmety (id NUMBER PRIMARY KEY, jmeno VARCHAR2(20));
SQL>  INSERT INTO predmety VALUES (1,'Architektura RDBS');
SQL>  INSERT INTO predmety VALUES (2,'Projekt z DBS');
SQL>  INSERT INTO predmety VALUES (3,'Autentizace');
SQL>  INSERT INTO predmety VALUES (4,'Zonglovani');

SQL>  CREATE TABLE uci (kdo NUMBER, co NUMBER);
SQL>  INSERT INTO uci VALUES (2,1);
SQL>  INSERT INTO uci VALUES (2,3);
SQL>  INSERT INTO uci VALUES (1,3);

-- 3) JOIN - spojeni ucitele se jmenem vyucovaneho predmetu
-- Pozor: ve vysledku nejsou zobrazeni ucitele, kteri nic neuci ani
-- predmety, ktere nikdo neuci.
SQL>  SELECT ucitele.jmeno, predmety.jmeno AS Predmet FROM predmety, ucitele, uci WHERE
ucitele.id=uci.kdo AND uci.co=predmety.id;

JMENO                PREDMET
-------------------- --------------------
Riha                 Architektura RDBS
Riha                 Autentizace
Matyas               Autentizace

-- 4) OUTER JOIN - zakladni join nam nevrati takove zaznamy z prvni tabulky, ktere nemaji odpovidaji zaznam (cizi klic) z druhe tabulky a naopak.
-- Resenim je pouzit "levy" (resp. "pravy") join. Levy join prochazi vsechny zaznamy v prvni tabulce (resp. druhe) a hleda k nim odpovidajici zaznamy z druhe (resp. prvni) tabulky. 
-- Pokud odpovidajici zaznam nenalezne, nahradi jej hodnotou NULL. Na vystup tak obdrzime i hodnoty, ktere nemaji v druhe tabulce odpovidajici zaznam.

-- 4A) vypis identifikaci predmetu, ktery uci dany ucitel
-- zobrazi se i ucitele, ktery nic neuci
SQL>  SELECT ucitele.jmeno, uci.co FROM ucitele, uci WHERE ucitele.id =
uci.kdo(+);

JMENO                        CO
-------------------- ----------
Matyas                        3
Riha                          1
Riha                          3
Svenda

-- 4B) vypis identifikaci ucitele, kteri uci dany predmet
-- zobrazi se i predmet, ktery nikdo neuci.
SQL>  SELECT predmety.jmeno, uci.kdo FROM predmety, uci WHERE predmety.id =
uci.co(+);

JMENO                       KDO
-------------------- ----------
Architektura RDBS             2
Projekt z DBS
Autentizace                   2
Autentizace                   1
Zonglovani

-- doplneni dotazu 4A) o nalezeni jmen predmetu dle identifikaci
SQL>  SELECT ucitele.jmeno, predmety.jmeno FROM ucitele, uci, predmety WHERE
ucitele.id = uci.kdo(+) AND uci.co=predmety.id(+);

JMENO                JMENO
-------------------- --------------------
Matyas               Autentizace
Riha                 Architektura RDBS
Riha                 Autentizace
Svenda

-- doplneni dotazu 4B) o nalezeni jmen ucitelu dle identifikace
SQL>  SELECT predmety.jmeno, ucitele.jmeno FROM ucitele, predmety, uci WHERE
predmety.id = uci.co(+) AND uci.kdo=ucitele.id(+);

JMENO                JMENO
-------------------- --------------------
Architektura RDBS    Riha
Projekt z DBS
Autentizace          Riha
Autentizace          Matyas
Zonglovani

-- 5) Hierarchicke dotazy
-- Mame tabulku firma s oraganizacni strukturou firmy. Mame-li vypsat jmeno
-- zamestnance a jmeno jeho primeho nadrizeneho, jde to lehce. Chceme-li
-- i jmeno nadrizeneho nadrizeneho, je to mozne zapsat pomoci spojeni 3 tabulek
-- firma. Obecne, zname-li maximalni pocet stupnu hierarchie, muzeme je vypsat.
-- Neni-li vsak pocet stupnu omezen urcitou konstantou, nemuzeme pomoci relacni
-- algebry vypsat kompletni hierarchii. Proto je do syntaxe oraclu pridana
-- specialni konstrukce pro praci s hierarchiemi. Klausule "CONNECT BY PRIOR"
-- specifikuje vazbu predchudce-naslednik, a pripadne klausule "START WITH"
-- specifikuje, ktera vetev nas zajima.
SQL>  DROP TABLE firma;
SQL>  CREATE TABLE firma (id NUMBER, jmeno VARCHAR2(20), mgr NUMBER);
SQL>  INSERT INTO firma VALUES (1,'Zdenek',NULL);
SQL>  INSERT INTO firma VALUES (2,'Jirka',1);
SQL>  INSERT INTO firma VALUES (3,'Jirinka',1);
SQL>  INSERT INTO firma VALUES (4,'Jitka',2);
SQL>  SELECT * FROM firma;

        ID JMENO                       MGR
---------- -------------------- ----------
         1 Zdenek
         2 Jirka                         1
         3 Jirinka                       1
         4 Jitka                         2


-- nadrizeny nadrizeneho zamestnance (bez pouziti hierarchickych dotazu)
SQL>  SELECT a.jmeno AS "Zamestnanec", b.jmeno AS "Sef", c.jmeno AS "Sefa sef" FROM firma a, firma b, firma c WHERE a.mgr=b.id AND b.mgr=c.id;

Zamestnanec          Sef                  Sefa sef
-------------------- -------------------- --------------------
Jitka                Jirka                Zdenek

SQL>  SELECT a.jmeno AS "Zamestnanec", b.jmeno AS "Sef", c.jmeno  AS "Sefa sef" FROM firma a, firma b, firma c WHERE a.mgr=b.id(+) AND b.mgr=c.id(+);

Zamestnanec          Sef                  Sefa sef
-------------------- -------------------- --------------------
Jitka                Jirka                Zdenek
Jirka                Zdenek
Zdenek
Jirinka              Zdenek

SQL>  SELECT a.jmeno AS "PodPodrizeny", b.jmeno AS "Podrizeny", c.jmeno AS "Sef" FROM firma a, firma b, firma c WHERE a.mgr(+)=b.id AND b.mgr(+)=c.id;

PodPodrizeny         Podrizeny            Sef
-------------------- -------------------- --------------------
Jitka                Jirka                Zdenek
                     Jirinka              Zdenek
                     Jitka                Jirka
                                          Jirinka
                                          Jitka

-- vyuziti hierrachickeho dotazu. Vazba predchudce naslednik na sloupce mgr a id 
-- vyhodnocovani se provede pouze pro zamestnance, ktery ma id = 4 (Jitka)
-- promenna LEVEL obsahuje aktualni hodnotu "zanoreni" dotazu
SQL>  SELECT LEVEL, id AS "Podrizeny", mgr AS "Sef" FROM firma CONNECT BY PRIOR mgr=id START WITH id=4;

     LEVEL  Podrizeny        Sef
---------- ---------- ----------
         1          4          2
         2          2          1
         3          1


-- opacny smer hierarchie. zaciname vedoucim a smerujeme k jeho podrizenym
SQL>  SELECT LEVEL, mgr AS "Sef", id AS "Podrizeny" FROM firma CONNECT BY PRIOR id=mgr START WITH mgr=1;

     LEVEL        Sef  Podrizeny
---------- ---------- ----------
         1          1          2
         2          2          4
         1          1          3


-- vypis vsech dotazu pro vsechny "vetve" (tedy pro vsechny zamestnance)
SQL>  SELECT level, id AS "Podrizeny", mgr AS "Sef" FROM firma CONNECT BY PRIOR mgr=id;

     LEVEL  Podrizeny        Sef
---------- ---------- ----------
         1          1
         1          2          1
         2          1
         1          3          1
         2          1
         1          4          2
         2          2          1
         3          1