Image
16.5.2016 0 Comments

Databázy / 8. časť

Späť na úvod >> Späť na seriál

V predchádzajúcich častiach sme sa pri vysvetľovaní príkazu SELECT zaoberali iba jednou tabuľkou. Toto sa však v praxi používa zriedka. Veľmi často sa výstupné zostavy skladajú zo spojenia dvoch alebo aj viacerých tabuliek. Spojiť tabuľky potrebujeme vtedy, ak v jednej tabuľke nie sú všetky nami požadované informácie. A tak sa tentoraz budeme venovať spájaniu tabuliek, ktorému sa po anglicky hovorí JOIN.

Vytvorenie cvičných tabuliek
Aby sme si vysvetlili túto tematiku, vytvoríme dve pomocné tabuľky, na ktorých budeme spájanie tabuliek precvičovať. Prvá tabuľka sa nazýva CITATEL; sú v nej uložené cvičné mená jednotlivých čitateľov a identifikačné číslo vypožičanej literatúry. Druhá tabuľka nesie názov LITERATURA a obsahuje identifikačné číslo a názov literatúry, ktorú si môžu jednotliví čitatelia vypožičať. Už vieme, že nie je veľmi vhodné dávať do jednej tabuľky meno čitateľa a úplný názov knihy, ktorú si požičal, napr. Hrbatý, Teória relativity. Veď kto by stále vypisoval celé názvy u všetkých čitateľov, keď je podstatne jednoduchšie zapísať iba identifikačné číslo príslušnej literatúry. (Poznámka: Okrem toho by takto zostavená databáza odporovala zásadám návrhu podľa tzv. normálnych foriem, čo sme si ešte nevysvetľovali. Aj naša doteraz používaná tabuľka KNIHA čiastočne odporuje týmto princípom, a preto ju budeme neskôr upravovať. Zatiaľ však na vysvetlenie základov SQL úplne vyhovuje.)

meno                id_lit

Novak

1

Hrbaty

2

Janík

NULL

Bartak

4

Horakova

1

Tab. 1  CITATEL

 

meno                      id_lit

NULL

Sipkova Ruzenka

1

Amaterske radio

2

Teoria relativity

3

Cestovny poriadok ZSR

Tab. 2  LITERATURA

Všimnime si, že v prvej tabuľke je pri mene Janik  prázdna hodnota (null). To znamená, že pán Janík nemá v tomto okamihu vypožičanú nijakú knihu. Podobne v druhej tabuľke je zaznamenané, že kniha o Šípkovej Ruženke nemá ešte pridelené výpožičkové číslo, napr. z dôvodu, že len teraz bola zakúpená a nestihla jej vedúca knižnice priradiť príslušné číslo.

My sme už dostatočne skúsení databázisti, takže teraz nebudem uvádzať dobre známy postup, ako tieto tabuľky vytvoriť.

Typy spojení
Väzby medzi tabuľkami používajú rôzne typy spojení. Väčšina z nich vychádza z normy SQL92, ale každý databázový stroj prináša používateľovi niektoré viac či menej príjemné zlepšenia.

Typy spojenia v SQL sa rozdeľujú do dvoch hlavných skupín:
-      vnútorné spojenia
-      vonkajšie spojenia

Vnútorné spojenia
Triviálne spojenie (Trivial Join)

Tento typ spojenia sa tak trochu vymyká z rámca definícií. Ale keďže sa často v literatúre spomína, aj my si ho objasníme. Ide o spojenie jednej tabuľky so samou sebou. Takže nejde o nič iné ako jednoduchý select danej tabuľky, napr.:
> select * from citatel;

Jednoduché spojenie cez jeden stĺpec
Pozrime sa znovu na tabuľku CITATEL. Vidíme, že je v nej uvedené len akési číslo príslušnej literatúry, ktorú si ten-ktorý čitateľ vypožičal. A keďže z tejto tabuľky nevieme, o akú literatúru ide, chceme, aby sa vypísal zoznam čitateľov a názov literatúry, ktorú si požičali. Tu už musíme použiť informácie z oboch tabuliek:

Použijeme príkaz:
> select * from citatel, literatura where citatel.id_lit = literatura.id_lit;

ktorý hovorí, aby sa vypísali všetky stĺpce z obidvoch tabuliek CITATEL aj LITERATURA, ktoré spĺňajú podmienku, že číslo v stĺpci id_lit v tabuľke CITATEL sa zhoduje s číslom id_lit v tabuľke LITERATURA. Ak sa znova pozrieme do uvedených tabuliek, vidíme, že výpis č. 2 je pravdivý, lebo sa obidva stĺpce id_lit zhodujú:

Čo je to za zvláštny zápis: citatel.id_lit?
Ak má stĺpec niektorej tabuľky rovnaký názov ako iný stĺpec v inej tabuľke, musíme špecifikovať, z ktorej tabuľky uvažovaný stĺpec vlastne je. Na to sa používa tzv. bodkový zápis  (dobre známy z objektového programovania). Jeho všeobecný tvar je:
názov_tabuľky.názov_stĺpca

napr.:     citatel.meno
V prípade, že by sme chceli spájať tabuľky z rôznych databáz  (áno, aj to je niekedy žiaduce), použijeme ešte konkrétnejší zápis:
názov_databázy. názov_tabuľky.názov_stĺpca

napr.:     kniznica.citatel.meno

Ak však používame tabuľky len v rámci jednej databázy, vystačíme s menej jednoznačným zápisom.
Uvedený výpis príkazu SELECT môžeme upraviť s použitím slova JOIN takto:
>select meno, nazov from citatel JOIN literatura where citatel.id_lit = literatura.id_lit;

Čo táto veta znamená? Voľne by sme ju mohli preložiť asi takto:
Vypíš stĺpce MENO a NAZOV  z tabuľky CITATEL, spojenej s tabuľkou LITERATURA, kde číslo v stĺpci id_lit v tabuľke CITATEL sa zhoduje s číslom id_lit v tabuľke LITERATURA. Na výpise č. 3 je nami požadovaná informácia:

Z uvedených príkladov je zrejmé, že konštrukcie s JOIN alebo čiarkou (,) sú úplne identické.

Určenie podmienky na spojenie tabuliek
Podmienka
citatel.id_lit = literatura.id_lit

zaisťuje, že vo výsledku bude u každého čitateľa uvedený iba ten riadok tabuľky LITERATURA, ktorý obsahuje názov literatúry s rovnakým číslom, ako si vypožičal čitateľ.
Keby sme túto podmienku neuviedli, vykonal by sa kartézsky súčin oboch tabuliek. To by znamenalo, že ku každému riadku tabuľky CITATEL by sa vyhľadali všetky riadky tabuľky LITERATURA. Výsledok takéhoto dopytu bude mať počet riadkov rovný počtu čitateľov krát počet literatúry (5 × 4 = 20):
> select * from citatel join literatura;

Z výpisu č. 4 vidíme, že nedáva zmysel. Pán Novák si predsa požičal iba Amatérske rádio, ostatnú literatúru nechcel. Nadbytočné riadky môžeme nájsť aj u ostatných čitateľov. Správne sú iba tie riadky, kde sú v oboch číselných stĺpcoch rovnaké hodnoty, teda 6., 10. a 12. riadok výpisu. Preto zadávame pri spájaní tabuliek podmienku, ktorá obmedzí riadky na tie, ktoré chceme dostať do výpisu. Zadávaná podmienka nemusí byť vždy na rovnosť stĺpcov.  Často sa používa podmienka príslušnosti do určitého intervalu.

Použitie spojenia tabuliek bez podmienky – kartézskeho súčinu
Existujú prípady, keď chceme zámerne využiť vlastnosti kartézskeho súčinu – vytvorenie všetkých kombinácií riadkov z oboch tabuliek (metóda každý s každým). Ako už vieme, v  tomto prípade nebudeme zadávať nijakú podmienku na spojenie oboch tabuliek.

Vonkajšie spojenie
Doteraz sme pracovali s tzv. vnútorným spojením tabuliek, ktorému sa po anglicky hovorí INNER JOIN. Do výsledného výpisu boli zahrnuté iba tie riadky z oboch tabuliek, pre ktoré bola nájdená zodpovedajúca hodnota v druhej tabuľke. Pozrime sa opäť na výpis č. 3. Vidíme, že do výsledku neboli zahrnutí tí čitatelia, ktorí nemajú zadané číslo literatúry (Janík) alebo ich vypožičaná literatúra neexistuje (Barták). Navyše vo výsledku nie je ani literatúra, ktorú si nikto nepožičal (Cestovný poriadok ŽSR) alebo ešte nemá pridelené číslo (Šípková Ruženka).

[POZOR! Podmienka citatel.id_lit = literatura.id_lit nie je splnená ani v prípade, keď citatel.id_lit = NULL (Janik) a literatura.id_lit =NULL (Sipkova Ruzenka) v 3. riadku výpisu č. 4. Výsledkom porovnania je totiž zase NULL, nie hodnota TRUE (áno), potrebná na potvrdenie podmienky rovnosti.]

Ľavé vonkajšie spojenie
Existuje spôsob spojenia, ktorý umožňuje zaradiť do výsledku aj tie riadky, pre ktoré nebola nájdená zodpovedajúca hodnota v druhej tabuľke. Takto môžeme vypísať zoznam kníh a im zodpovedajúcich čitateľov, v ktorom bude uvedená aj literatúra, ktorú si nik nepožičal. Alebo naopak, vypíšeme zoznam všetkých čitateľov, ktorí si nepožičali nijakú literatúru. Takémuto spojeniu sa hovorí vonkajšie spojenie.
Vonkajšie spojenia môžu byť dvojakého druhu – ľavé (LEFT) a pravé (RIGHT). MySQL server podporuje iba ľavé vonkajšie spojenie. (A my si ukážeme, ako dosiahnuť pravé spojenie.)

Ľavé vonkajšie spojenie vytvoríme konštrukciou LEFT JOIN. Použitím tohto spojenia dosiahneme vo výslednom výpise zahrnutie všetkých riadkov z ľavej (teda z prvej) tabuľky. Ak nebol nájdený zodpovedajúci riadok v pravej tabuľke, budú vo výsledku  hodnoty NULL vo všetkých stĺpcoch použitých z druhej tabuľky.
Použitá konštrukcia je zrejmá z výpisu č. 5:

Vidíme, že páni Janík a Barták majú v pravom stĺpci hodnotu NULL. Janík si nič nepožičal a Barták má číslo pôžičky, ktorá neexistuje.
Pred chvíľou sme si povedali, že ak máme rovnaké názvy stĺpcov v jednotlivých tabuľkách, pre jednoznačnosť musíme použiť bodkový zápis. V prípade ľavého spojenia si však zápis môžeme zjednodušiť konštrukciou USING (meno_porovnávaného_stĺpca), tak ako je to na výpise č. 6:

LEFT OUTER JOIN
Je ekvivalent príkazu LEFT JOIN. Používa sa pre kompitibilitu s drivermi ODBC.

Pravé vonkajšie spojenie
Použitím tohto spojenia dosiahneme vo výslednom výpise zahrnutie všetkých riadkov z pravej (teda z druhej) tabuľky. Ak nebol nájdený zodpovedajúci riadok v ľavej tabuľke, budú vo výsledku  hodnoty NULL vo všetkých stĺpcoch použitých z  prvej tabuľky. Ako vieme, MySQL nepodporuje pravé spojenie. My ho však vieme vytvoriť z ľavého spojenia jednoduchým prehodením poradia spájaných tabuliek okolo príkazu LEFT JOIN.
oužitá konštrukcia je zrejmá z výpisu č. 7:

Tu vidíme, že Šípková Ruženka a Cestovný poriadok ŽSR obsahujú v ľavom stĺpci, kde sa nachádza meno čitateľa,  hodnotu NULL, lebo tá prvá ešte nemá pridelené číslo a cestovný poriadok si nik nepožičal.
V praxi sa veľmi často používa práve ľavé (LEFT JOIN) spojenie.

Technické detaily spájania tabuliek
Spájanie tabuliek je časovo náročná činnosť. Preto je veľmi vhodné zamyslieť sa nad spôsobom, ktorým sú tabuľky spájané, a následne sa pokúsiť vhodným zadaním príkazu SELECT zrýchliť spracovanie. Pri spájaní tabuliek ide všeobecne o kartézsky súčin dvoch relácií. Výsledný počet záznamov bude rásť exponenciálne s počtom riadkov vo vstupujúcich tabuľkách. Naším základným cielom by preto malo byť čo najviac obmedziť počet riadkov v tabuľkách ešte pred vlastným spájaním. Napríklad ak chceme zistiť informácie o knižniciach v Trenčianskom kraji, obmedzíme najprv tabuľku knižníc iba na knižnice v tomto regióne a až potom výsledok budeme spájať s tabuľkami kníh, autorov a iné. Ďalej je veľmi dôležité, aby sme vždy použili obmedzenia pre spájané stĺpce (v JOIN alebo WHERE), a tým čo najviac znížili počet riadkov vo výslednom výpise. Našťastie dnešné databázové stroje majú zabudované veľmi rýchle spájacie mechanizmy, ktoré mnohé optimalizácie vykonávajú automaticky bez nášho zásahu.

Naše spojenie
Vráťme sa však k našej databáze KNIZNICA a tabuľkám KNIHA a ZANER. Vieme, že tabuľka KNIHA obsahuje stĺpec CIS_ODD, ktorým sa odvoláva na podobný stĺpec v tabuľke ZANER.
Použijeme už známu konštrukciu LEFT JOIN USING.

Na výpise č. 8 vidíme už podstatne prijateľnejší výpis, aký sme používali v predošlých častiach seriálu.
Nadnes by stačilo, nabudúce sa začneme zaoberať jednou z najdôležitejších činností SQL servera – jeho administráciou.

Zobrazit Galériu

Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Tipy a triky: Ako na snímku obrazovky na akomkoľvek počítači s Windows?

02.12.2016 00:13

Ak snímky obrazovky robíte často apotrebujete napríklad funkcie na posun stránok alebo snímanie zobrazenia pri vyššom rozlíšení displeja, zrejme používate nejakú špecializovanú aplikáciu. Väčšina použ ...

Ako na to 1

Tipy a triky: Ako aplikácii prednastaviť spúšťanie s administrátorskými právami?

30.11.2016 00:10

Väčšina aspoň trochu skúsenejších používateľov vie, že aj keď máte na operačnom systéme Windows vytvorený administrátorský účet, aplikácie pre bezpečnosť nefungujú vždy splnými administrátorskými práv ...

Ako na to 2

Tipy a triky: Ako vypnúť uzamykaciu obrazovku vo Windows 10?

29.11.2016 00:10

Rozčuľuje vás, že pred každým prihlásením doúčtu vášho počítača musíte prejsť uzamykacou obrazovkou? Windows 10 na tejto obrazovke ukazuje čas,dátum anejakú zaujímavú fotografiu zrôznych kútov sveta. ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá