Zadanie

Ak máte akékoľvek otázky ohľadom tejto úlohy, napíšte Maji na maja@ksp.sk

Blíži sa polročné vysvedčenie a učitelia majú plné ruky práce. Musia zaokrúhľovať známky, vypisovať vysvedčenia a hlavne sa pri tom všetkom nepomýliť. A to vôbec nie je ľahká úloha. Okrem toho, že učitelia musia mať prehľad o vedomostiach ich žiakov, musia sa vedieť orientovať aj v školskom informačnom systéme, ktorý je samozrejme elektronický. A aby ste si vedeli skontrolovať, či Vám učitelia správne zaokrúhlili známky, mali by ste sa naučiť so systémom poriadne robiť aj vy. Poďme teda na to :).

Úloha

Táto úloha sa zaoberá prácou s databázami a jazykom SQL. Ak ste tieto pojmy nikdy nepočuli, všetko vám vysvetlí tutoriál, ktorý nájdete na https://prask.ksp.sk/navody/databazy-sql/. Nezľaknite sa jeho dĺžky, už počas čítania budete schopní riešiť jednotlivé podúlohy. Informačný systém (databáza) našej školy sa nachádza na https://people.ksp.sk/~prask/specialne/3/2/3/. Popis jednotlivých tabuliek, ktoré v tejto databáze budete používať nájdete tu: https://prask.ksp.sk/navody/udaje_tabuliek/. Vašou úlohou je spustiť nejaké príkazy na stránke s databázou a s ich pomocou odpovedať na otázky v jednotlivých podúlohách.

Ako riešenie úlohy odovzdávate slovný popis, ktorý má obsahovať: odpoveď na zadanú otázku, príkazy, ktoré ste pri riešení danej podúlohy použili a stručný popis toho, prečo ste použili práve uvedené príkazy.

  1. (1 bod) Na škole sa vyučuje jeden neštandardný predmet. Napíšte nám, aké je jeho ID.
  2. (1 bod) Dostal niekto 24. 12. jednotku?
  3. (1 bod) Koľko žiakov sa volá Jozef alebo Juraj alebo má priezvisko Novák?
  4. (1 bod) Aký je vekový rozdiel medzi najmladším a najstarším žiakom?
  5. (1 bod) Ktorý učiteľ učí 3.B matematiku?
  6. (1 bod) Napíš mená všetkých učiteľov matematiky.
  7. (1 bod) Ktorý študent dostal naposledy päťku?
  8. (2 body) Ktorý študent dostal naposledy päťku z matematiky od profesorky Vlnovej?
  9. (2 body) V ktorom predmete sa žiakom najviac darilo v septembri? Teda taký, z ktorého bola najlepšia priemerná známka za september?
  10. (2 body) Ktorá trieda má najlepší priemer známok z matematiky?
  11. (2 body) Ktorý učiteľ nadŕža dievčatám? Teda taký, ktorý dáva viac jednotiek dievčatám ako chlapcom? Zaujíma nás učiteľ, ktorý dal napríklad dievčatám celkovo 150 jednotiek a chlapcom iba 93.

Bonusová úloha: (2 body) Ktorý učiteľ dáva priemerne lepšie známky triede, ktorej je aj triedny učiteľ? Teda je to učiteľ, ktorý nadŕža svojim študentom.

Podúloha a)

Na škole sa vyučuje jeden neštandardný predmet. Napíšte nám, aké je jeho ID.

Z databázy si necháme vypísať zoznam všetkých predmetov, ktoré sa na škole vyučujú, pomocou príkazu

SELECT * FROM predmety;

V zozname predmetov potom nájdeme vskutku neštandardný predmet s názvom Obrana proti čiernej mágii. Vidíme, že jeho ID je 14.

Podúloha b)

Dostal niekto 24. 12. jednotku?

Keďže nás zaujímajú známky, má zmysel sa pozerať do tabuľky znamky. Ako vidíme, v tejto tabuľke je ku každej známke zaznačený aj dátum, v ktorom bola udelená a takisto jej hodnota. Nás zaujímajú iba jednotky, ktoré boli udelené 24.12., preto použijeme príkaz WHERE, pomocou ktorého vieme vybrať riadky s konkrétnymi hodnotami. Jednotlivé podmienky pospájame pomocou AND, keďže chceme aby platili všetky naraz.

SELECT *
FROM znamky
WHERE hodnotenie_den = 24 AND hodnotenie_mesiac = 12 AND hodnotenie = 1;

Hľadaný deň, mesiac a hodnotenie nepíšeme v úvodzovkách, pretože tieto polia majú formát čísla. Z odpovede v databáze vidíme, že v daný deň bolo udelených až 58 jednotiek.

Podúloha c)

Koľko žiakov sa volá Jozef alebo Juraj alebo má priezvisko Novák?

Hľadáme žiakov, takže budeme používať tabuľku ziaci. Vypísať však chceme len tých, ktorí majú meno Jozef alebo Juraj alebo majú priezvisko Novák. Na toto opäť použijeme príkaz WHERE, tentokrát ale jednotlivé časti pospájama slovom OR, pretože stačí, aby platila len jedna z podmienok.

SELECT *
FROM ziaci
WHERE meno = "Jozef" OR meno = "Juraj" OR priezvisko = "Novák";

Môžete si všimnúť, že vo výsledku je viacero Jozefov Novákov. Každý z nich má však unikátne ID, takže sú to odlišní žiaci s rovnakým meomm. Každý jednotlivý žiak s menom Jozef Novák je však vypísaný iba raz, napriek tomu, že spĺňa obe podmienky. To je spôsobené tým, ako databáza prehľadáva tabuľku – postupne prechádza všetky záznamy (žiakov) a pre každý záznam overuje zadanú podmienku. Ak podmienka platí, záznam vypíše.

Všimnite si, že jednotlivé mená sme museli dať do úvodzoviek. Odpoveďou je počet riadkov výsledku, teda 280.

Podúloha d)

Aký je vekový rozdiel medzi najmladším a najstarším žiakom?

V tejto podúlohe nás zaujímajú všetci žiaci, preto nebudeme musieť použiť príkaz WHERE. To čo potrebujeme je usporiadať žiakov podľa dátumu narodenia. Na to slúži príkaz ORDER BY. Pomocou neho vieme určiť, na základe ktorých vlastností sa má výsledok (v našom prípade celá tabuľka ziaci) zoradiť. Na nájdenie najstaršieho žiaka poslúži nasledovný príkaz.

SELECT *
FROM ziaci
ORDER BY narodeniny_rok ASC, narodeniny_mesiac ASC, narodeniny_den ASC;

Slovo ASC (teda stúpajúco) sme použiť nemuseli, keďže takéto zoradenie sa používa štandardne. Tak či tak, prvý riadok výsledku predstavuje najstaršieho žiaka, ktorý sa narodil 2.9.2000.

Na nájdenie najmladšieho žiaka sa potom buď pozrieme na spodok tabuľky, alebo príkaz otočíme pomocou DESC (klesajúco).

SELECT *
FROM ziaci
ORDER BY narodeniny_rok DESC, narodeniny_mesiac DESC, narodeniny_den DESC;

Zistíme, že najmladší žiak sa narodil 30.8.2009. Vekový rozdiel najmladšieho a najstaršieho žiaka je teda takmer 9 rokov.

Podúloha e)

Ktorý učiteľ učí 3.B matematiku?

Hľadáme meno učiteľa, ktorý učí 3.B. matematiku. Na to by nám mohla poslúžiť tabuľka vyucovania, v ktorej sú záznamy o tom, ktorý učiteľ učí ktorú triedu ktorý predmet. Jediný problém je, že v tejto tabuľke sa nachádajú iba IDčka učiteľov, tried a predmetov.

Aby sme k ID vedeli priradiť aj konkrétne meno, musíme použiť aj tabuľky triedy, ucitelia a predmety. Tieto tabuľky potrebujeme spojiť na základe rovnakých ID, čo spravíme pomocou príkazu WHERE. Napríklad bude musieť platiť, že vyucovania.id_triedy = triedy.id.

Ako sa už písalo v tutoriáli, keď do FROM zadáme viacero tabuliek, ich obsahy sa skombinujú. Každý riadok jednej tabuľky sa spojí s každým riadkom druhej. V našom prípade dokonca dostaneme až štvorice riadkov. Veľa z nich nám však vôbec nepomôže. Získať záznam, ktorý spája učiteľa Jánoša (ID 3) s vyučovaním, ktoré učil Boška (ID 8), je asi zbytočné. Keďže sa však ich IDčka líšia, vieme ich ľahko vyfiltrovať vo WHERE. Preto nám ostanú iba zmysluplné záznamy, ktoré spájajú učiteľov s ich vyučovaniami. A samozrejme rovnako to funguje aj pre ucitelia a predmety.

Naviac vo WHERE upresníme aj to, že hľadáme iba triedu 3.B. a predmet matematika.

SELECT predmety.meno, triedy.meno, ucitelia.meno, ucitelia.priezvisko 
FROM vyucovania, ucitelia, triedy, predmety 
WHERE ucitelia.id = vyucovania.id_ucitela AND vyucovania.id_predmetu = predmety.id
AND vyucovania.id_triedy = triedy.id AND triedy.meno = "3.B" AND predmety.meno = "Matematika";

Vidíme, že v tomto prípade sme za FROM potrebovali dosadiť až štyri tabuľky. Takisto aby výsledok nebol príliš komplikovaný, SELECT nám určil, ktoré stĺpce nás zaujímajú. V tomto prípade iba meno triedy, predmetu a meno učiteľa (stačilo by síce vypísať iba meno učiteľa, takto si to však vieme skontrolovať).

Výsledkom je učiteľ Alfréd Gašparovič.

Podúloha f)

Napíš mená všetkých učiteľov matematiky.

Postup je rovnaký ako v predošlej podúlohe, akurát nepotrebujeme použiť tabuľku triedy. To, ktorú triedu daný učiteľ učí nás totiž nezaujíma, dôležité je len to, že učí matematiku.

SELECT ucitelia.meno, ucitelia.priezvisko 
FROM vyucovania, ucitelia, predmety 
WHERE ucitelia.id = vyucovania.id_ucitela AND vyucovania.id_predmetu = predmety.id
AND predmety.meno = "Matematika";

Výsledkom je tabuľka 33 učiteľov. Je tam však drobný problém. Ak sa lepšie pozrieme na mená týchto učiteľov, zistíme, že niektoré z nich sa opakujú. Keď sa však nad tým zamyslíme, nie je to až tak prekvapivé. Riadky totiž vyberáme na základe rôznych riadkov vyucovania. Ale jeden učiteľ matematiky učí matematiku pravdepodobne viacero tried. Za každú triedu (teda iný riadok v tabuľke vyucovania), ktorú nejaký učiteľ učí matematiku sa tento učiteľ dostane do výsledku.

Aby sme teda zistili, koľko rôznych učiteľov učí na našej škole matematiku, musíme z výsledných záznamov odstrániť duplikáty. To môžeme spraviť ručne, pričom nám veľmi pomôže, ak si do nášho príkazu pridáme ORDER BY ucitelia.priezvisko. Alebo na to môžeme použiť už existujúci príkaz SQL – SELECT DISTINCT. Ten funguje úplne rovnako ako príkaz SELECT, ale v získanom výsledku navyše odstráni opakujúce sa riadky.

SELECT DISTINCT ucitelia.meno, ucitelia.priezvisko 
FROM vyucovania, ucitelia, predmety 
WHERE ucitelia.id = vyucovania.id_ucitela AND vyucovania.id_predmetu = predmety.id
AND predmety.meno = "Matematika";

Zistíme, že na škole učí matematiku 13 učiteľov.

Podúloha g)

Ktorý študent dostal naposledy päťku?

Tabuľka znamky obsahuje iba ID žiakov. Potrebujeme si tieto spojiť tabuľky znamky a ziaci tak, ako v predchádzajúcich úlohách cez rovnosť IDčok. Takisto do príkazu WHERE zadáme, že hľadáme iba päťky a výsledok zoradíme príkazom ORDER BY, aby sa nám najnovšia päťka zobrazila ako prvý riadok výsledku.

SELECT ziaci.meno, ziaci.priezvisko, znamky.hodnotenie,
hodnotenie_rok, hodnotenie_mesiac, hodnotenie_den 
FROM znamky, ziaci 
WHERE znamky.id_ziaka = ziaci.id AND hodnotenie = 5
ORDER BY hodnotenie_rok DESC, hodnotenie_mesiac DESC, hodnotenie_den DESC;

Ako vidíme, pätiek bolo udelených posledný deň v škole pomerne dosť. Najjednoduchší spôsob ako ponechať vo výsledku iba tieto pätky, je do WHERE pridať podmienku na daný rok, mesiac a deň. Naviac si musíme dať pozor, aby sme niekoho nezarátali viackrát, na čo nám opäť poslúži SELECT DISTINCT. Ani to však nestačí, pretože ak sú nejaký dvaja žiaci menovci, tak ich SELECT DISTINCT prehlási za duplikáty. Aby sme sa tomu vyhli, pridáme do výsledku aj ziaci.id. Dvaja ľudia s tým istým menom budú mať totiž rôzne ID.

SELECT DISTINCT ziaci.id, ziaci.meno, ziaci.priezvisko, znamky.hodnotenie,
hodnotenie_rok, hodnotenie_mesiac, hodnotenie_den 
FROM znamky, ziaci 
WHERE znamky.id_ziaka = ziaci.id AND hodnotenie_rok = 2016 AND hodnotenie_mesiac = 6
AND hodnotenie_den = 30 AND hodnotenie = 5;

Zistíme, že týchto pätiek bolo rozdaných 73 rôznym študentom.

Podúloha h)

Ktorý študent dostal naposledy päťku z matematiky od profesorky Vlnovej?

Táto podúloha sa síce veľmi ponáša na tú predchádzajúcu, predsa je však o dosť náročnejšia.

V predchádzajúcej podúlohe sme spojili tabuľky znamky a ziaci, vďaka čomu sme o každej známke zistili aj to, ktorý konkrétny žiak ju získal. Naviac sme si nechali iba päťky. Teraz však potrebujeme zistiť aj to, ktorý učiteľ túto známku dal. Bohužiaľ, v tabuľke znamky nie je id_ucitela, jediné, čím si vieme pomôcť je id_predmetu. Pripojme teda tabuľku predmety, opäť podľa rovnosti IDčok. Vďaka tomu vieme do WHERE pridať podmienku predmety.meno = "Matematika", takže nám ostanú už iba pätorky z matematiky.

Matematiku však môže na škole učiť aj viacero učiteľov. Ako teda zistíme, ktoré pätky dala Vlnová? Určite však platí, že konkrétnu triedu učí matematiku iba jeden učiteľ. A tabuľka vyucovania nám podáva presne túto informáciu. Preto do riešenie pripojíme tabuľku vyucovania, pričom si musíme dať pozor, aby sme porovnávali aj znamky.id_predmetu a aj ziaci.id_triedy.

V tomto momente už o každej známke vieme z akého predmetu bola udelená, v ktorej triede, ktorému žiakovi a takisto poznáme ID učiteľa, ktorý ju dal. Stačí teda podľa vyucovania.id_ucitela pripojiť tabuľku ucitelia a vybrať iba známky, ktoré udelila učiteľka s priezviskom Vlnová.

    SELECT *
    FROM znamky, ziaci, predmety, vyucovania, ucitelia
    WHERE znamky.id_ziaka = ziaci.id AND znamky.hodnotenie = 5
    AND znamky.id_predmetu = predmety.id AND predmety.meno = "Matematika"
    AND znamky.id_predmetu = vyucovania.id_predmetu
    AND ziaci.id_triedy = vyucovania.id_triedy AND vyucovania.id_ucitela = ucitelia.id
    AND ucitelia.priezvisko = "Vlnová"
    ORDER BY znamky.hodnotenie_rok DESC, znamky.hodnotenie_mesiac DESC,
    znamky.hodnotenie_den DESC;

Samozrejme napísať takýto zložitý výraz je náročné. Aj pri písaní sa však dalo postupovať po krokoch, presne ako vo vzorovom riešení. Stačilo tabuľky pridávať jednu po druhej, vždy si overiť, že aktuálny príkaz dáva správny výsledok a až potom pridať ďalšiu tabuľku a ďalšiu podmienku. Dôležité len bolo nezľaknúť sa.

Zistíme, že naposledy dostali päťku z matematiky od učiteľky Vlnovej žiaci: Edita Melichárová, Kamil Lipa a Erik Loja.

Podúloha i)

V ktorom predmete sa žiakom najviac darilo v septembri? Teda taký, z ktorého bola najlepšia priemerná známka za september?

V tejto podúlohe potrebujeme zistiť, v ktorom predmete mali žiaci v septembri najlepšiu priemernú známu. Čo znamená, že budeme musieť použiť príkaz GROUP BY.

Ak si zoberieme všetky známky, je ľahké z nich vybrať tie, ktoré boli udelené v septembri. Následne ich chceme rozdeliť do skupín podľa predmetu. A práve na to slúži príkaz GROUP BY predmety.id. Názvy stĺpcov za GROUP BY udávajú, podľa ktorých hodnôt sa majú tieto riadky zoskupiť. Následne vieme na zvyšné stĺpce použiť agregačnú funkciu, akou je napríklad primer AVG. Dostávame pomerne jednoduchý príkaz.

SELECT predmety.meno, AVG(znamky.hodnotenie) AS priemer
FROM znamky, predmety
WHERE znamky.id_predmetu = predmety.id AND znamky.hodnotenie_mesiac = 9
GROUP BY predmety.id
ORDER BY priemer;

Všimnite si, že na konci sme výsledok usporiadali podľa vypočítaného priemeru. Aby sme mohli za ORDER BY dať tento priemer, museli sme si príslušný stĺpec pomenovať týmto menom, na čo slúžil príkaz AS.

Odpoveďou je Prvouka s priemerom 2.8934.

Podúloha j)

Ktorá trieda má najlepší priemer známok z matematiky?

Po všetkých predchádzajúcich úlohách by nám táto už nemala robiť žiadne problémy. Spojením tabuliek znamky a ziaci sa dozvieme, ktorú triedu navštevuje žiak, ktorý dostal konkrétnu známku. Aby sme naviac nemuseli pracovať iba s IDčkami tried a predmetov, pridáme si k nim tabuľky predmety a triedy.

Teraz už vieme veľmi jednoducho ponechať iba známky z matematiky a pomocou GROUP BY ich rozdeliť do skupín podľa jednotlivých tried (je jedno či na to použijeme triedy.id, triedy.meno alebo ziaci.id_triedy). Následne vieme pre každú triedu získať priemernú známku pomocou AVG.

    SELECT triedy.meno, AVG(znamky.hodnotenie) AS priemer
    FROM znamky, ziaci, predmety, triedy
    WHERE znamky.id_ziaka = ziaci.id AND id_predmetu = predmety.id
    AND predmety.meno = "Matematika" AND ziaci.id_triedy = triedy.id
    GROUP BY ziaci.id_triedy
    ORDER BY priemer;

S priemerom 2.7733 vyhrá trieda 9.B..

Podúloha k)

Ktorý učiteľ nadŕža dievčatám? Teda taký, ktorý dáva viac jednotiek dievčatám ako chlapcom? Zaujíma nás učiteľ, ktorý dal napríklad dievčatám celkovo 150 jednotiek a chlapcom iba 93.

A prichádza na rad posledná (nerátajúc bonus) podúloha. A jej riešenie dalo skutočne zabrať. Pri jej riešení ste totiž museli buď mierne improvizovať, alebo si naštudovať o SQL ešte niečo naviac. Poďme si teda ukázať, ako sa to dalo vyriešiť.

Ako prvé musíme vedieť spočítať, koľko jednotiek rozdal daný učiteľ chlapcom a koľko dievčatám. Zamerajme sa najskôr na chlapcov1. Aj pomocou predchádzajúcich úloh by sme mali vedieť vytvoriť tabuľku, v ktorej sa budú nachádzať všetky jednotky, ktoré dostali chlapci a pri nich aj meno učiteľa, ktorý túto známku dal.

Rovnako ako v podúlohe h) musíme správne spojiť tabuľky znamky, ziaci, vyucovania a ucitelia. Pozor si musíte dať hlavne na to, aby ste ošetrili rovnosť všetkých troch hodnôt z tabuľky vyucovania, teda id_ucitela, id_triedy a id_predmetu. Inak sa vám môže stať, že zarátate známku, ktorú dal daný učiteľ z rovnakého predmetu v inej triede. Alebo v prípade, že učiteľ učí v tej istej dva predmety a vy neošetríte vyucovania.id_predmetu = znamky.id_predmetu, budete jednotky z nich rátať dvakrát. Následne pomocou WHERE ľahko ponecháme iba jednotky, ktoré dostali chlapci.

Teraz chceme tieto jednotky zoskupiť podľa učiteľa, ktorý ich dal. Do GROUP BY preto musíme dať mená stĺpcov, podľa ktorých chceme riadky zoskupovať. Najlepšie bude použiť samotné IDčka učiteľov, aby sme sa vyhli problémom, keď je na škole viacero učiteľov s tým istým menom aj priezviskom. No a ako bolo napísané v tutoriáli, na spočítanie riadkov výsledku slúži agregačná funkcia COUNT. Keďže sa však jedná o jednotky, rovnako dobre by sme mohli použiť SUM, keďže súčet jednotiek je ich počet. Dostávame nie až tak komplikovaný príkaz.

    SELECT ucitelia.meno, ucitelia.priezvisko, COUNT(znamky.hodnotenie) AS pocet_chlapci
    FROM znamky, ziaci, vyucovania, ucitelia
    WHERE znamky.id_ziaka = ziaci.id AND ziaci.id_triedy = vyucovania.id_triedy
    AND vyucovania.id_ucitela = ucitelia.id AND ziaci.pohlavie = "C"
    AND znamky.hodnotenie = 1 AND vyucovania.id_predmetu = znamky.id_predmetu
    GROUP BY ucitelia.id;

Vytvoriť rovnakú tabuľku aj pre dievčatá následne nie je problém. Stačí ak "C" zmeníme za "D". Ako však porovnáme počty jednotiek, ktoré dostali chlapci a dievčatá?

Ak ste sa rozhodli improvizovať, pomôcť vám môže tabuľkový kalkulátor, akým je napríklad Excel. Jednoducho si necháte vypísať obe tabuľky, skopírujete ich do tabuľkového kalkulátora a v ňom už veľmi jednoducho viete spočítať rozdiel dvoch čísel vo všetkých riadkoch. Len si musíte dať pozor, aby ste dali k sebe výsledky pre tých istých učiteľov.

Takto ste však ručne urobili niečo, čo celý čas za vás robilo SQL. Predsa sa to musí dať spraviť aj v ňom. A veruže dá. Odpoveďou sú dočasné tabuľky. Uvedommte si, že vždy keď ste spustili nejaký príkaz SELECT, tak výsledkom bola tabuľka. Niekedy prázdna, niekedy len s jedným riadkom a občas ich obsahovalo vyše \(20\,000\). Ale zakaždým to bola iba nejakým spôsobom zmodifikovaná tabuľka.

Pre programátora by teda malo byť prirodzené, že si vie takúto tabuľku odložiť na neskoršie použitie, ako to robí bežne s premennými. Či už natrvalo, alebo iba dočasne, kým mu neskončí aktuálny výpočet. To mu okrem iného aj umožní rozdeliť svoju prácu. Namiesto toho aby písal jeden obrovský SQL príkaz, môže napísať niekoľko kratších, zrozumiteľnejších a prehľadnejších, ktoré nadväzujú jeden na druhý. A ako vidíme v tejto úlohe, niekedy to bez použitia pomocných tabuliek ani nejde.

No a na toto slúži príkaz CREATE VIEW meno AS. Ten vytvorí dočasnú tabuľku, do ktorej si môžete uložiť svoje medzivýpočty. Jeho použitie je veľmi ľahké. Ak chcete vytvoriť tabuľku, použijete tento príkaz, doplníte meno, ktorým chcete túto tabuľku nazývať a za AS dáte príkaz SELECT, ktorý hovorí, ako túto tabuľku naplniť.

Vďaka tomu si vieme vytvoriť dve tabuľky, jednu pre počty jednotiek chlapcov (chlapci), druhú pre počty jednotiek dievčat (dievcata). Potom tieto tabuľky spojíme podľa mien učiteľov a do SELECT dáme vypísať rozdiel počtu jednotiek v tabuľke dievcata a v tabuľke chlapci. Zistíme, že najviac nadržiava dievčatám Dávid Kočka, ktorý im dal až o 38 viac jednotiek ako chlapcom.

    CREATE VIEW chlapci AS
    SELECT ucitelia.meno, ucitelia.priezvisko, COUNT(znamky.hodnotenie) AS pocet_chlapci
    FROM znamky, ziaci, vyucovania, ucitelia
    WHERE znamky.id_ziaka = ziaci.id AND ziaci.id_triedy = vyucovania.id_triedy
    AND vyucovania.id_ucitela = ucitelia.id AND ziaci.pohlavie = "C"
    AND znamky.hodnotenie = 1 AND vyucovania.id_predmetu = znamky.id_predmetu
    GROUP BY ucitelia.id;

    CREATE VIEW dievcata AS
    SELECT ucitelia.meno, ucitelia.priezvisko, COUNT(znamky.hodnotenie) AS pocet_dievcata
    FROM znamky, ziaci, vyucovania, ucitelia
    WHERE znamky.id_ziaka = ziaci.id AND ziaci.id_triedy = vyucovania.id_triedy
    AND vyucovania.id_ucitela = ucitelia.id AND ziaci.pohlavie = "D"
    AND znamky.hodnotenie = 1 AND vyucovania.id_predmetu = znamky.id_predmetu
    GROUP BY ucitelia.id;

    SELECT chlapci.meno, chlapci.priezvisko,
    dievcata.pocet_dievcata - chlapci.pocet_chlapci AS rozdiel
    FROM chlapci, dievcata
    WHERE chlapci.meno = dievcata.meno AND chlapci.priezvisko = dievcata.priezvisko
    ORDER BY rozdiel DESC;

Poznámka k dočasným tabuľkám a nášmu webovému rozhraniu: Ak v našom webovom rozhraní spustíte príkaz CREATE VIEW, vytvorí sa dočasná tabuľka, ktorá tam bude až do momentu kým nerefreshnete stránku. To znamená, že ak sa pokúsite druhýkrát spustiť príkaz CREATE VIEW s tým istým menom bez toho, aby ste stránku refreshli, program vám vypíše chybu, lebo taká tabuľka už bude existovať a on ju nemôže len tak prepísať.

Bonusová úloha

Ktorý učiteľ dáva priemerne lepšie známky triede, ktorej je aj triedny učiteľ? Teda je to učiteľ, ktorý nadŕža svojim študentom.

No čo? Zistili ste ktorý učiteľ najviac nadržiaval svojim?

Tak ako v predcházajúcej úlohe, aj tu si budeme musieť pomôcť dočasnými tabuľkami. V jednej pre každého učiteľa zistíme, aké dáva priemerné známky žiakom svojej triedy a v druhej, aké dáva priemerné známky žiakom mimo svojej triedy.

Toto nie je až také ťažké a v mnohom sa to podobá na to, čo sme už robili v predchádzajúcich úlohách. Naviac však budeme používať hodnotu triedy.id_ucitela, v ktorej je uložené ID triedneho učiteľa každej triedy. Takisto za zmienku stojí, že prvýkrát použijeme negáciu, keď budeme chcieť, aby sa trieda, do ktorej žiak chodí nerovnala triede, ktorej je daný učiteľ triedny. Na to poslúži príkaz NOT.

Takto získané dve tabuľky potom spojíme na základe mien učiteľov a príkazom WHERE vyberieme všetky riadky, kde je priemer známok triedy učiteľa nižší ako priemer zvyšných žiakov, ktorých učí. Zistíme, že nadŕža až 24 učiteľov, pričom najväčší vinník je Urban Borka (2.8354 oproti 3.0784) a najmenší vinník je Levoslav Franko (3.0063 oproti 3.0083).

    CREATE VIEW triedny_ucitel AS
    SELECT ucitelia.id, ucitelia.meno, ucitelia.priezvisko,
    AVG(znamky.hodnotenie) AS priemerna_znamka_trieda
    FROM znamky, ucitelia, vyucovania, ziaci, triedy
    WHERE vyucovania.id_ucitela = ucitelia.id AND vyucovania.id_triedy = ziaci.id_triedy
    AND ziaci.id_triedy = triedy.id AND triedy.id_ucitela = ucitelia.id
    AND znamky.id_ziaka = ziaci.id AND znamky.id_predmetu = vyucovania.id_predmetu
    GROUP BY ucitelia.id;

    CREATE VIEW iny_ucitel AS
    SELECT ucitelia.id, ucitelia.meno, ucitelia.priezvisko,
    AVG(znamky.hodnotenie) AS priemerna_znamka_netrieda
    FROM znamky, ucitelia, vyucovania, ziaci, triedy
    WHERE vyucovania.id_ucitela = ucitelia.id AND vyucovania.id_triedy = ziaci.id_triedy
    AND ziaci.id_triedy = triedy.id AND NOT triedy.id_ucitela = ucitelia.id
    AND znamky.id_ziaka = ziaci.id AND znamky.id_predmetu = vyucovania.id_predmetu
    GROUP BY ucitelia.id;

    SELECT *
    FROM triedny_ucitel, iny_ucitel
    WHERE triedny_ucitel.id = iny_ucitel.id
    AND triedny_ucitel.priemerna_znamka_trieda < iny_ucitel.priemerna_znamka_netrieda
    ORDER BY iny_ucitel.priemerna_znamka_netrieda - triedny_ucitel.priemerna_znamka_trieda DESC;

Záver

Dúfame, že sa vám úloha s SQL páčila. Je to rozhodne zaujímavý a užitočný programovací jazyk. Webový portál s databázou ostane naďalej prístupný, takže si kľudne môžete vyskúšať programy zo vzorového riešenia, poprípade zistiť nejakú ďalšiu zaujímavú vlastnosť, ktorú učitelia na tejto škole majú.

No a koho to zaujíma, tak dáta v tejto databáze boli samozrejme umelé. Aj mená vznikli iba náhodnou kombináciou mien a priezvisk z voľne dostupných slovníkov. Ako však vidíte, aj z takejto malej a pomerne jednoduchej databázy sa dali získať vcelku zaujímavé dáta.


  1. Nech nás nemôžu obviniť, že nadržiavame

Diskusia

Tu môžte voľne diskutovať o riešení, deliť sa o svoje kusy kódu a podobne.

Pre pridávanie komentárov sa musíš prihlásiť.

  • Michaela Pastulová

    22. február 2017 21:00

    Úloha bola veľmi zaujímavá, som rada, že som ju mohla riešiť, i keď nie úplne úspešne :) Ocenila by som niečo na takýto spôsob aj nabudúce.