Tento návod patrí k úlohe Polročné vysvedčenie. Najlepšie tento návod pochopíte, ak budete počas neho skúšať postupne riešiť jednotlivé podúlohy. Hrať sa s našou databázou a SQL môžete tu: https://people.ksp.sk/~prask/specialne/3/2/3/.

Príklady tabuliek použitých v tomto návode nie vždy (alebo úplne) zodpovedajú tabuľkám v reálnej databáze. Zoznam tabuliek aj s názvami stĺpcov v týchto tabuľkách môžete nájsť tu: https://prask.ksp.sk/navody/udaje_tabuliek/

Čo sú to databázy?

Možno ste o databázach nikdy nepočuli, ale stoja na pozadí každej zložitejšej webovej stránky, určite by ste ich našli vo svojom telefóne alebo v obľúbenej počítačovej hre. Databázy sú spôsob, akým si počítačové programy ukladajú informácie pre neskoršie použitie. To, čo uložíte do databázy, tam zostane, aj keď vypnete počítač. Toto isté by sa dalo povedať napríklad aj o Wordovom dokumente. Ten ale nie je veľmi vhodný na čítanie pre počítač. Databáza má tú výhodu, že dáta v nej sú pekne usporiadané, tak aby sa ich počítaču dobre čítalo a zároveň sa odtiaľ dajú údaje rýchlo získať a rýchlo zapísať. Webové stránky používajú databázy napr. na ukladanie si zoznamu užívateľov, aj váš účet na Facebooku je určite uložený niekde v databáze :).

A načo je SQL?

SQL je jazyk, ktorým môžete s databázami komunikovať. Pomocou SQL viete databáze povedať veci ako napr. „nájdi mi všetkých študentov, ktorí majú viac ako 15 rokov". Samozrejme túto požiadavku musíte napísať v SQL. Ako tento jazyk používať uvidíte nižšie.

Tabuľky

Každá databáza má svoje tabuľky (angl. tables). V tabuľke býva zoznam podobných objektov, u ktorých nás zaujímajú rovnaké vlastnosti. Napr. majme databázu skola, a v nej tabuľky ziaci a ucitelia. Tabuľka ziaci by mohla vyzerať takto:

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
0 Peter Rusnák 2 1.12.2005
1 Monika Králová 2 1.12.2005
2 Michal Boža 3 18.3.2008
3 Dávid Petrovič 4 1.12.2005
4 Monika Kasová 4 7.11.2006

Tabuľka ucitelia by zase mohla vyzerať takto:

ID_ucitela

Meno_ucitela

Trieda_ucitela

0

Mgr. Koberec

6

1

Mgr. Osem

7

2

Mgr. Prefíkaná

3

3

Mgr. Kvetináč

V databázach používame nasledujúce termíny:

  • riadky (angl. rows): jednotlivé záznamy objektov v databáze

  • názvy stĺpcov (angl. fields, poslovenčene fieldy): vlastnosti jednotlivých objektov, ktoré zadávame do databázy. V tabuľke ziaci sú to napr. : Meno_ziaka, Datum_narodenia...

  • stĺpce (angl. Columns): hodnoty v jednotlivom stĺpci, na ktoré sa vieme pozerať a pýtať sa na ne.

  • ID objektu(z anglického Identity): číslo, podľa ktorého databáza rozlišuje záznamy. Dva záznamy môžu mať rovnaké všetky stĺpce, ale ID musí byť vždy iné pre každý objekt v tabuľke (unikátne, angl. unique). Napr. môžeme mať dvoch študentov, ktorí sa obaja volajú Jožko Mrkvička a narodili sa 2.3.2005 (aj keď je to nepravdepodobné, stať sa to môže), ale vďaka ID ich budeme vedieť rozlíšiť. V skutočnom živote je ID napríklad vaše rodné číslo.

Príkaz SELECT

Najzákladnejší príkaz v jazyku SQL je príkaz SELECT. Slúži na vypísanie dát z tabuľky. Napisaný vyzerá takto:
SELECT nazov_stlpcov FROM nazov_tabulky;
Príkaz vyberie z tabuľky s názvom nazov_tabulky stĺpce nazov_stlpcov. SQL príkazy môžu byť napísané na viacerých riadkoch kvôli prehľadnosti, koniec príkazu označujeme bodkočiarkou. A skutočný príkaz preto môže vyzerať napríklad:
SELECT ID_ucitela, Meno_ucitela FROM ucitelia;
Výsledok tohto príkazu by potom vyzeral takto:

ID_ucitela

Meno_ucitela

0

Mgr. Koberec

1

Mgr. Osem

2

Mgr. Prefíkaná

3

Mgr. Kvetináč

Všimnite si, že trieda učiteľa sa nevypísala, pretože sme špecifikovali, že chceme vypísať iba ID a meno. Alebo môžeme napísať takýto príkaz:
SELECT * FROM ziaci;
Hviezdička ("*") znamená v SQL jazyku „všetko“, konkrétne v tomto príkaze sa myslí všetky stĺpce tabuľky ziaci. Príkaz by vypísal toto:

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
0 Peter Rusnák 2 1.12.2005
1 Monika Králová 2 1.12.2005
2 Michal Boža 3 18.3.2008
3 Dávid Petrovič 4 1.12.2005
4 Monika Kasová 4 7.11.2006

Keď ste sa dostali v tutoriáli už takto ďaleko, môžete si trochu oddýchnuť od čítania a skúsiť vyriešiť podúlohu a).

Príkaz WHERE

Vďaka príkazu SELECT vieme vybrať hociktoré stĺpce z hociktorej tabuľky. Problém ale je, že vždy vyberieme všetky riadky danej tabuľky. A tabuľky môžu mať strašne veľa záznamov a my môžeme hľadať napríklad iba človeka s konkrétnym menom. Na to, aby sme to vedeli urobiť rýchlejšie, slúži príkaz WHERE. Príkazom WHERE vieme špecifikovať, aké hodnoty by mali mať jednotlivé stĺpce záznamov, ktoré chceme vybrať. Napríklad, ak chceme vybrať všetkých žiakov 2. ročníka, urobíme to takto:
SELECT * FROM ziaci WHERE Rocnik_ziaka=2;

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
0 Peter Rusnák 2 1.12.2005
1 Monika Králová 2 1.12.2005

Alebo takto: v tomto príklade vyberieme všetkých žiakov, ktorí sa volajú Peter, pričom špecifikujeme, ktoré stĺpce chceme zobraziť (tie sa môžu líšiť od tých, ktoré použijeme v podmienke WHERE):
SELECT ID_ziaka, Rocnik_ziaka FROM ziaci WHERE Meno_ziaka="Peter";

ID_ziaka Rocnik_ziaka
0 2

Pozor: Všimnite si, že je rozdiel, či porovnávame hodnotu v tabuľke s číslom alebo so slovom. Ak porovnávame so slovom, je treba slovo dať do úvodzoviek, čísla sa do úvodzoviek nedávajú (toto je veľmi zjednodušené vysvetlenie, môže nastať aj prípad, že číslo budeme dávať do úvodzoviek, napr. keď je to názov niečoho). Hlavný dôvod však je, že ak by sme mali napríklad tabuľku Peter tak počítaču musíme vysvetliť, kedy hovoríme o názve tejto tabuľky a kedy o mene.

Podmienka vo vnútri WHERE nemusí obsahovať iba jedno porovnanie; pomocou slov OR (alebo) a AND (a zároveň) vieme spojiť viacero podmienok dokopy.

Príkaz SELECT * FROM ziaci WHERE Meno_ziaka='Monika' AND Rocnik_ziaka=4; vyberie z tabuľky ziaci všetkých žiakov, ktorí sa volajú Monika a zároveň (AND) chodia do štvrtej triedy.

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
4 Monika Kasová 4 7.11.2006

Príkaz:
SELECT * FROM ucitelia WHERE Predmety_ucitela="Občianska náuka" OR Trieda_ucitela=7;
zase vyberie z tabuľky ucitelia učiteľov, ktorí učia občiansku náuku alebo (OR) sú triedny učitelia 7. triede.

Podmienky môžeme ľubovoľne kombinovať a zoskupovať pomocou zátvoriek:
SELECT * FROM tabuľka WHERE podmienka1 AND (podmienka2 OR podmienka3);
by vybral také riadky, kde by platila podmienka1 a zároveň aspoň jedna z podmienok podmienka2 a podmienka3.

Ak naopak chcem vybrať všetky riadky, ktoré nespĺňajú nejakú podmienku, môžeme použiť výraz NOT, napr:

SELECT * FROM ziaci WHERE NOT Meno_ziaka='Peter'; vyberie z tabuľky ziaci všetkých žiakov, ktorí sa nevolajú Peter. Podmienky s NOT môžeme aj kombinovať s AND a OR:
SELECT * FROM tabuľka WHERE NOT Meno_ziaka='Peter' AND NOT Rocnik_ziaka=3;

Teraz už môžete vyskúšať vyriešiť podúlohy b) a c).

Príkaz ORDER BY

Poradie vypisovania výsledkov môžeme ovplyvniť pomocou príkazu ORDER BY:
SELECT * FROM ziaci ORDER BY Meno_ziaka;
vyberie všetky záznamy z tabuľky ziaci a zoradí ich (abecedne) podľa ich mena od "A" po "Z".

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
3 Dávid Petrovič 4 1.12.2005
2 Michal Boža 3 18.3.2008
4 Monika Kasová 4 7.11.2006
1 Monika Králová 2 1.12.2005
0 Peter Rusnák 2 1.12.2005

Ak nakoniec, za ORDER BY pripojíme slovo DESC dostaneme výsledky zoradené naopak, v predošlom prípade by boli zoradene od "Z" po "A". ORDER BY vie zoraďovať výsledky aj podľa viacerých kritérií - najprv zoradí výsledky podľa prvého kritéria, ak je pre nejaké výsledky toto kritérium rovnaké, tak ich zoradí podľa druhého kritéria atď. V našej tabuľke žiakov máme napr. 2 Moniky. Ak by sme použili príkaz:
SELECT * FROM ziaci ORDER BY Meno_ziaka, Rocnik_ziaka;

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
3 Dávid Petrovič 4 1.12.2005
2 Michal Boža 3 18.3.2008
1 Monika Králová 2 1.12.2005
4 Monika Kasová 4 7.11.2006
0 Peter Rusnák 2 1.12.2005

tabuľka by sa zoradila najskôr podľa mena, a ak sú mená rovnaké, zoradili by sa podľa ročníka.

Alebo môžeme skúsiť aj skombinovať príkazy WHERE a ORDER BY:

SELECT * FROM ziaci WHERE Rocnik_ziaka>2 ORDER BY Meno_ziaka;

ID_ziaka Meno_ziaka Priezvisko Rocnik_ziaka Datum_narodenia
3 Dávid Petrovič 4 1.12.2005
2 Michal Boža 3 18.3.2008
4 Monika Kasová 4 7.11.2006

A teraz si môžete vyskúšať vyriešiť podúlohy d) a e). Ak sa budete v úlohe e) príliš trápiť, prečítajte si najskôr nasledujúcu časť.

Spájanie tabuliek

Najskôr si vytvoríme 2 veľmi krátke tabuľky, ktoré sa nám budú pre túto úlohu veľmi hodiť. Prvá tabuľka sa vola mena:

Meno Priezvisko
Julia Hukova
Jonatan Huka

Druhá tabuľka sa vola cisla:

Cislo Kam
0905234566 Domov
0905234523 Do prace

Čo by sa stalo, ak by sme spustili výraz SELECT * from cisla, mena? Tento príkaz by skombinoval každý riadok z tabuľky cisla a spojil ho s každým riadkom v tabuľke mena a zobrazil ich spolu v jednom riadku. Vyzeralo by to asi takto:

Cislo Kam Meno Priezvisko
0905234566 Domov Julia Hukova
0905234523 Do prace Julia Hukova
0905234566 Domov Jonatan Huka
0905234523 Do prace Jonatan Huka

Táto operácia v podstate kombinuje všetky riadky v prvej tabuľke s riadkami z druhej tabuľky. Nazýva sa kartézsky súčin. A pýtate sa načo nám to je? Potom, čo tabuľky spojíme, môžeme zadávať podmienky na kombinácie týchto riadkov. Uvidíte neskôr :).

Vytvorme si teraz ešte jednu tabuľku znamky, kde budeme zaznamenávať známky. Pre každú známku si budeme pamätať, kto ju dostal a z akého predmetu bola (a samozrejme každá známka musí mať svoje unikátne ID, pretože tu môže ľahko nastať situácia, kedy má jeden žiak viacero rovnakých známok z toho istého predmetu - záznamy by boli potom identické a systém by ich nevedel od seba odlíšiť.

Údaj o tom, kto danú známku dostal, si nemôžeme pamätať menom, lebo sa môže veľmi ľahko stať, že dvaja žiaci budú mať rovnaké meno (aj priezvisko) - preto si tento údaj musíme pamätať niečím unikátnym. Presne na takéto účely používame ID objektu(v tomto prípade ID_ziaka).

Predmet známky by sme tiež mali ukladať pomocou ID, ale kvôli prehľadnosti nám teraz postačí jeho názov a vedomie, že na škole nie sú dva predmety s rovnakým názvom (ak by boli, potom by sa nám známky z týchto predmetov pomiešali).

ID_znamky

Znamka

ID_ziaka

Predmet

0

5

0

Technická výchova

1

1

1

Matematika

2

1

3

Matematika

3

3

1

Občianska náuka

4

1

4

Biológia

5

2

3

Technická výchova

6

1

0

Chémia

Teraz by sme mohli chcieť zistiť napr. aké známky dostal Peter. Na to, aby sme to vedeli urobiť sami by sme sa najskôr potrebovali pozrieť do tabuľky ziaci a zistiť, aké ID má Peter. To si zapamätať, prejsť do tabuľky znamky a hľadať všetky známky, ktoré majú ID_ziaka také isté, ako Peter. To ale určite zakaždým robiť nechceme a práve na to existuje spôsob, ako tabuľky spájať dokopy.

Ak by ste sa chceli o tejto časti dozvedieť podrobnejšie, ďalšie informácie pribudnú časom na konci tutorialu. Odporúčame si ich prečítať, ak by ste sa chystali naozaj začať robiť niečo s databázami :). Na vyriešenie úlohy v Prasku Vám to ale netreba.

Ako by teda vyzeral príkaz, ktorý spojí naše dve tabuľky? Asi takto:
SELECT * FROM ziaci, znamky WHERE znamky.ID_ziaka = ziaci.ID_ziaka;

znamky.
ID_znamky

znamky.
Znamka

znamky.
ID_ziaka

znamky.
Predmet

ziaci.
ID_ziaka
ziaci.
Meno_ziaka
ziaci.
Priezvisko
ziaci.
Rocník_
ziaka
ziaci.
Datum_
narodenia

0

5

0

Technická výchova

0 Peter Rusnák 2 1.12.2005

1

1

1

Matematika

1 Monika Králová 2 1.12.2005

2

1

3

Matematika

3 Dávid Petrovič 4 1.12.2005

3

3

1

Občianska náuka

1 Monika Králová 2 1.12.2005

4

1

4

Biológia

3 Dávid Petrovič 4 1.12.2005

5

2

3

Technická výchova

3 Dávid Petrovič 4 1.12.2005

6

1

0

Chémia

0 Peter Rusnák 2 1.12.2005

Ako vidíte, museli sme špecifikovať, ktoré stĺpce tabuliek sa majú rovnať (ID_ziaka). Niekedy nemusíme chcieť vypísať z obidvoch tabuliek všetky dáta. Tak ako predtým môžeme špecifikovať, ktoré stĺpce chceme zobraziť. Avšak ak majú stĺpce v obidvoch tabuľkách rovnaké mená, môže dôjsť ku kolízii, preto je lepšie špecifikovať názov, tak, že najskôr napíšeme meno tabuľky, ktorej ten stĺpec má patriť a bodku, napr:

SELECT znamky.ID_znamky, znamky.Znamka, znamky.Predmet, ziaci.Meno_ziaka, ziaci.ID_ziaka

FROM znamky, ziaci

WHERE znamky.ID_ziaka=ziaci.ID_ziaka;

Spájať samozrejme môžete aj viac ako 2 tabuľky :).

A teraz ste pripravení riešiť úlohy f)-h). Veľa šťastia :).

Agregačné funkcie

Nezľaknite sa toho hrozivého názvu, agregačné funkcie sú veľmi užitočné a uľahčia vám veľa práce s databázami :). Sú tu funkcie, ktoré vedia zobrať nejaký stĺpec a z jeho dát niečo výratať, napr. priemer. Agregačné funkcie, ktoré sa Vám môžu hodiť sú:

  • AVG() - zoberie všetky hodnoty v stĺpci a spraví z nich (aritmetický) priemer. (ak slovo aritmetický nepoznáte, nevšímajte si ho)

  • COUNT() - spočíta počet riadkov v stĺpci

  • FIRST() - vráti prvú hodnotu v stĺpci

  • LAST() - vráti poslednú hodnotu v stĺpci

  • MAX() - vráti najväčšiu hodnotu v stĺpci

  • MIN() - vráti najmenšiu hodnotu v stĺpci

Začneme použitím funkcie AVG.

SELECT AVG(stlpec) AS pomenovanie FROM tabulka;

Tento príkaz zoberie dáta v stlpci stlpec z tabuľky tabulka a vypočíta jeho priemer, ktorému potom priradí názov pomenovanie.

Príklad: povedzme, že chceme zistiť priemer všetkých známok v našej databáze. Použijeme príkaz

SELECT AVG(Znamka) AS Priemerna_znamka FROM znamky;

Tento príkaz v podstate hovorí: zober všetky hodnoty známok, ktoré máš v tabuľke znamky, spriemeruj ich a túto hodnotu pomenuj Priemerna_znamka.

Priemerna_znamka
2

Už vieme, aká je priemerná známka všetkých študentov, ale možno by sme chceli vedieť priemernú známku pre jedného študenta. Na to slúži príkaz GROUP BY, vďaka ktorému bude agregačná funkcia vedieť, že má robiť priemer iba pre jedného študenta. Za GROUP BY zadávame názvy stĺpcov, podľa ktorých chceme riadky združovať dokopy. Príkaz potom ako keby najskôr zoskupí k sebe všetky riadky, ktoré majú rovnakú hodnotu stĺpca, ktorý sme uviedli za GROUP BY a následne vykoná zadanú agregačnú funkciu v rámci každej skupiny. Ukážme si príklad:

SELECT AVG(Znamka) AS Priemerna_znamka, Meno_ziaka, Priezvisko

FROM znamky, ziaci

WHERE znamky.ID_ziaka=ziaci.ID_ziaka

GROUP BY Meno_ziaka, Priezvisko;

Priemerna_známka

ziaci.
Meno_ziaka
ziaci.
Priezvisko
2.5 Peter Rusnák
2 Monika Králová
1.33 Dávid Petrovič

Tento príkaz zoberie najskôr všetky riadky v tabuľkách znamky a ziaci a pospája ich dokopy tak, aby ID_ziaka zodpovedalo. To znamená, že dostaneme jednu veľkú tabuľku, kde o každej známke budeme vedieť aj ktorému žiakovi patrí a všetky vlastnosti tohto žiaka. Následne sa tieto riadky združia podľa parametrov v GROUP BY, teda podľa Meno_ziaka a Priezvisko. Takto sa vytvoria skupiny riadkov (známok), každá skupina obsahuje všetky známky jedného študenta. Následne sa vykoná SELECT, v ktorom sa vyberie z každej skupiny Meno_ziaka a Priezvisko a hodnoty známok v tejto skupine sa zpriemerujú - zistíme priemernú hodnotu známok, ktoré dostal tento študent.

Všimnite si, že v SELECT sme vybrali iba stĺpce, na ktoré sa použili agregačné funkcie alebo sa použili v GROUP BY. Čo by sa stalo, ak by sme napríklad napísali príkaz:

SELECT AVG(Znamka) AS Priemerna_znamka, Meno_ziaka, Priezvisko, znamky.Predmet

FROM znamky, ziaci

WHERE znamky.ID_ziaka = ziaci.ID_ziaka

GROUP BY Meno_ziaka, Priezvisko;

Príkaz by nevedel čo od neho chceme. V skupine žiaka je totiž veľa riadkov a každý z tých riadkov môže mať inú hodnotu znamky.Predmet. Pri Meno_ziaka a Priezvisko je to ľahké, lebo tie sú v skupine rovnaké. Pre hodnotu Znamka je to tiež v poriadku, lebo tam mu vysvetlíme, že z tých veľa hodnôt, čo má v skupine má spraviť priemer. Ale čo má spraviť s predmetom počítač netuší. Preto ak používame GROUP BY, tak v časti SELECT sa môžu buď nachádzať stĺpce z časti GROUP BY alebo na ne musíme použíť agregačné funkcie.

Priemerna_znamka

ziaci.
Meno_ziaka
ziaci.
Priezvisko
znamky.Predmet
2.5 Peter Rusnák ????????
2 Monika Králová ????????
1.33 Dávid Petrovič ????????

Predošlá tabuľka by sa pravdepodobne nikdy nevypísala, namiesto nej by sme dostali chybovú hlášku, ale vďaka nej môžete vidieť, ako by asi nad vašim príkazom počítač rozmýšlal :).

Nakoniec ešte môžeme chcieť vypísať iba študentov, ktorí majú priemernú známku menšiu ako 2. Asi by ste skúsili napísať niečo takéto:

SELECT AVG(Znamka) AS Priemerna_znamka, Meno_ziaka, Priezvisko, znamky.Predmet

FROM znamky, ziaci

WHERE znamky.ID_ziaka = ziaci.ID_ziaka AND AVG(Znamka)<2

GROUP BY Meno_ziaka, Priezvisko;

tento príkaz však vyhodí chybu. Pokiaľ totiž chceme stanoviť nejakú podmienku pre výsledok agregačnej funkcie, nepoužívame príkaz WHERE ale príkaz HAVING. Správny príkaz by mal vyzerať takto:

SELECT AVG(Znamka) AS Priemerna_znamka, Meno_ziaka, Priezvisko

FROM znamky, ziaci

WHERE znamky.ID_ziaka = ziaci.ID_ziaka

GROUP BY Meno_ziaka, Priezvisko

HAVING AVG(Znamka)<2;

Priemerna_znamka

ziaci.
Meno_ziaka
ziaci.
Priezvisko
1.33 Dávid Petrovič

Ak ste sa dostali v tutoriali až sem, môžete si vydýchnuť. Je to za vami :). Teraz by ste už mali byť schopní riešiť všetky podúlohy.

Čas poslednej úpravy: 23. január 2017 6:12