Druhý díl našeho seriálu byl věnován úvodu do příkazu SELECT. Slíbili jsme si, že se dnes podíváme na to, co jsou agregační funkce. Zkusíme si také vybrat data z více tabulek.
Druhý díl našeho seriálu byl věnován úvodu do příkazu SELECT. Slíbili jsme si, že se dnes podíváme na to, co jsou agregační funkce. Zkusíme si také vybrat data z více tabulek.
Pod pojmem agregační funkce si můžeme představit například funkci COUNT (ano, hádáte správně, vrátí počet záznamů) či funkci SUM. Zopakujme si zjednodušenou syntaxi příkazu SELECT:
SELECT [DISTINCT] položky FROM jméno_tabulky [WHERE podmínka_výběru] [GROUP BY položky, [HAVING podmínka_agregace]] [ORDER BY položky]
Standardně (v některých implementacích mohou být realizovány i některé další) je v SQL obsaženo pět agregačních funkcí - COUNT, SUM, MIN, MAX a AVG. Pro bližší vysvětlení rozšíříme naši tabulku z minulého dílu o položku (atribut) počet_dětí. Tabulka osoby tak bude mít následující podobu:
jméno |
příjmení |
rodné_číslo |
datum |
počet_dětí |
Karel |
Smolný |
580815/8777 |
3.12.1992 |
2 |
Marek |
Jurda |
650404/8956 |
2.11.1992 |
3 |
Martin |
Pavlásek |
720303/5511 |
28.3.1990 |
3 |
Pavel |
Jirásek |
551212/7877 |
26.3.1989 |
2 |
Pavla |
Nováková |
785308/4569 |
28.6.1997 |
5 |
Pavla |
Nováková |
555111/3042 |
28.5.1990 |
1 |
Romana |
Bourková |
745226/8820 |
3.5.1995 |
5 |
Význam jednotlivých agregačních funkcí je na první pohled patrný z jejich názvu. Na několika příkladech si ukažme, jak je můžeme použít.
SELECT MIN(počet_dětí), MAX (počet_dětí), AVG (počet_dětí) FROM osoby
dává výsledek:
MIN (počet_dětí) |
MAX (počet_dětí) |
AVG(počet_dětí) |
1 |
5 |
3 |
SELECT COUNT(
počet_
dětí)
FROM osoby WHERE počet_
dětí> 2
dává výsledek (tedy kolik osob má více dětí než 2):
Aź k tomuto místu se zdá, že vše je jasné a jednoduché. Problémy mohou nastat při používání klauzulí
GROUP BY a
HAVING. O první z nich lze říci, že nám vybrané řádky sdružuje do skupin podle zvolených položek. Druhá je pak podobná klauzuli
WHERE, avšak s tím rozdílem, že podmínka je vztažena na celou skupinu, nikoli na záznam.
GROUP BY tedy můžeme použít například ve chvíli, kdy potřebujeme rozdělit počet osob podle počtu jejich dětí:
SELECT počet_dětí, COUNT (počet_dětí) FROM osoby GROUP BY počet_dětí ORDER BY počet_dětí
dává výsledek:
počet_dětí |
COUNT(počet_dětí) |
1 |
1 |
2 |
2 |
3 |
2 |
5 |
2 |
Pokud nás zajímá jen takový počet dětí, který je alespoň u dvou osob, je vhodný čas na využití klauzule HAVING:
SELECT počet_dětí, COUNT (počet_dětí) FROM osoby GROUP BY počet_dětí HAVING COUNT (počet_dětí)>1 ORDER BY počet_dětí
dává výsledek (všimněte si, že nám vypadl řádek s jedním dítětem):
počet_dětí |
COUNT(počet_dětí) |
2 |
2 |
3 |
2 |
5 |
2 |
Možností, jak agregační funkce v SQL použít, je pochopitelně víc. Stejně tak je jejich dokonalé pochopení (a tedy i schopnost odpovídajícího využití) otázkou praktických zkušeností. Podstatné je si uvědomit, že jednotlivé klauzule příkazu SELECT lze mezi sebou kombinovat a takřka vždy tak získat odpověď na všechno, co se chceme dozvědět.
Dosud jsme pracovali pouze s jednou jedinou tabulkou. Jak postupovat, když potřebuji dvě tabulky spojit? V praktickém životě existují především dva požadavky na slučování dat z více (pro jednoduchost uvažujme dvě) tabulek. Prvním je získat podle klíčové položky, například podle rodného čísla, doplňující údaje o dané osobě. Těmi mohou být informace o předchozích zaměstnavatelích. Druhou možností je "sloučit" stejné (obsahující tytéž položky) tabulky či dva dotazy se shodnými položkami výběru. Například tehdy, máme-li tabulku zaměstnanců v podniku A i B a chceme získat seznam pracovníků obou dvou podniků. V prvním případě hovoříme o tzv. JOINu, ve druhém pak o UNIONu. Pro názornou ukázku si zaveďme další dvě tabulky - předchozích zaměstnavatelů a osob pracujících v jiné továrně (shodnou s nám již známou tabulkou osoby).
rodné_číslo |
předchozí_zaměstnavatel |
580815/8777 |
České dráhy |
580815/8777 |
FIMU |
650404/8956 |
Computer Press |
650404/8956 |
ČVUT |
650404/8956 |
VUT |
720303/5511 |
ČSAD Brno |
720303/5511 |
MHD Brno |
551212/7877 |
MHD Praha |
785308/4569 |
MHD Praha |
785308/4569 |
Slovenské dráhy |
785308/4569 |
MHD Bratislava |
555111/3042 |
ČVUT |
745226/8820 |
VUT |
745226/8820 |
Česká televize |
Jméno |
příjmení |
rodné_číslo |
datum |
počet_dětí |
David |
Mladý |
770511/4577 |
1.11.1992 |
1 |
Emil |
Starý |
880505/1155 |
2.10.1992 |
4 |
Jiří |
Nováček |
780503/1425 |
28.4.1990 |
1 |
Karel |
Pavel |
611110/1425 |
26.6.1991 |
5 |
Katka |
Silná |
675309/4569 |
22.6.1995 |
1 |
Milena |
Ničivá |
545212/4542 |
23.4.1992 |
2 |
Zdena |
Malá |
715812/8820 |
4.11.1995 |
1 |
První typ si tedy ukážeme na dotazu, který by nám měl zodpovědět na otázku, které předchozí zaměstnavatele měly osoby uvedené v tabulce osobyA. Dobře si povšimněte omezující podmínky na stejná rodná čísla. Bez ní by výsledkem dotazu byl kartézský součin obou tabulek.
SELECT a.rodné_číslo, a.jméno, a.příjmení, b.předchozí_zaměstnavatel FROM osobyA a, předchozí_zaměstnavatelé b WHERE a.rodné_číslo= b.rodné_číslo
dává výsledek:
a.rodné_číslo |
a.jméno |
a.příjmení |
b.předchozí_zaměstnavatel |
580815/8777 |
Karel |
Smolný |
České dráhy |
580815/8777 |
Karel |
Smolný |
FIMU |
650404/8956 |
Marek |
Jurda |
Computer Press |
650404/8956 |
Marek |
Jurda |
ČVUT |
650404/8956 |
Marek |
Jurda |
VUT |
720303/5511 |
Martin |
Pavlásek |
ČSAD Brno |
720303/5511 |
Martin |
Pavlásek |
MHD Brno |
551212/7877 |
Pavel |
Jirásek |
MHD Praha |
785308/4569 |
Pavla |
Nováková |
MHD Praha |
785308/4569 |
Pavla |
Nováková |
Slovenské dráhy |
785308/4569 |
Pavla |
Nováková |
MHD Bratislava |
555111/3042 |
Pavla |
Nováková |
ČVUT |
745226/8820 |
Romana |
Bourková |
VUT |
745226/8820 |
Romana |
Bourková |
Česká televize |
Tečková notace (a, b) nám určuje příslušnost jednotlivých položek ke konkrétní tabulce. Její používání je nutné tehdy, když není možné jednoznačně určit, z které tabulky chcete položku vybrat. V zájmu lepší přehlednosti by se však měla používat vždy.
Následující příklad nám ukazuje druhý typ dotazu nad více tabulkami. Podotýkám, že pro UNION je nutná shoda ve vybíraných položkách.
SELECT jméno,příjmení,rodné_číslo,datum FROM osobyA UNION SELECT jméno,příjmení,rodné_číslo,datum FROM osobyB
dává výsledek:
jméno |
příjmení |
rodné_číslo |
datum |
Karel |
Smolný |
580815/8777 |
3.12.1992 |
Marek |
Jurda |
650404/8956 |
2.11 .1992 |
Martin |
Pavlásek |
720303/5511 |
28.3.1990 |
Pavel |
Jirásek |
551212/7877 |
26.3.1989 |
Pavla |
Nováková |
785308/4569 |
28.6.1997 |
Pavla |
Nováková |
555111/3042 |
28.5.1990 |
Romana |
Bourková |
745226/8820 |
3.5.1995 |
David |
Mladý |
770511/4577 |
1.11.1992 |
Emil |
Starý |
880505/1155 |
2.10.1992 |
Jiří |
Nováček |
780503/1425 |
28.4.1990 |
Karel |
Pavel |
611110/1425 |
26.6.1991 |
Katka |
Silná |
675309/4569 |
22.6.1995 |
Milena |
Ničivá |
545212/4542 |
23.4.1992 |
Zdena |
Malá |
715812/8820 |
4.11.1995 |
V tomto a předchozím díle jsme se zajímali pouze o to, jak data z tabulek "přečíst" a otázka jejich vkládání či změna zůstávala stranou. Možná jste už někdy slyšeli něco o příkazech INSERT a UPDATE. Pokud ne, nevadí - příště si jejich funkci podrobně vysvětlíme.
Předchozí díly
Nevíte si s SQL rady? Zeptejte se!2. díl o SQL - začínáme s příkazem Select Víte, co je SQL? Ne? Nevadí - dnes začínáme!