MySQL (25) - hrátky se seskupenými záznamy
Jak vytřídit již jednou seskupené záznamy? O tom je dnešní díl seriálu MySQL. Dozvíte se třeba, jak vypočítat průměrné platy ve firmě.
17.6.2005 09:00 |
Petr Zajíc
| Články autora
| přečteno 36997×
V předchozím díle jsme rozebrali seskupování záznamů. Dnes se na
toto téma ještě podíváme, protože minule jsem vám zdaleka o této věci
neřekl všechno. Co dalšího tedy můžeme uvést o MySQL, příkazu
SELECT a seskupování položek?
Jiný příklad na seskupování
Zatím neumíme vybírat seskupené záznamy. Připomeňme si z minulého dílu
myšlenku, že při seskupování záznamů můžeme použít klauzuli WHERE pro
výběr záznamů, které se mají vzít v úvahu. To znamená, že ještě
předtím, než je cokoli seskupeno, jsou vybrány jen odpovídající
záznamy. Protože jsme si minule pohrávali s myšlenkou sestavit dotaz,
který by vybral pracovníky s nadprůměrným platem, pojďme to nyní
udělat. Mějme například následující tabulku:
create table pracovnik
(jmeno varchar(50), oddeleni varchar(20), plat int);
insert into pracovnik (jmeno, oddeleni, plat) values ('Jarda',
'marketing', 14000);
insert into pracovnik (jmeno, oddeleni, plat) values ('Pepa',
'marketing', 16000);
insert into pracovnik (jmeno, oddeleni, plat) values ('Honza',
'marketing', 18000);
insert into pracovnik (jmeno, oddeleni, plat) values ('Jana', 'výroba',
10500);
insert into pracovnik (jmeno, oddeleni, plat) values ('Kamil',
'výroba', 12500);
insert into pracovnik (jmeno, oddeleni, plat) values ('Petr', 'výroba',
13500);
Na první pohled sice z této tabulky vidíme, že lidé v marketingu
mají větší peníze než lidé ve výrobě, ale to nebylo naším cílem. S tím,
co již umíme, můžeme pomocí agregačních funkcí vypočítat průměrný plat
ve firmě. V nejjednodušším případě třeba takto:
select
sum(plat)/count(*) from pracovnik;
Z tohoto dotazu byste mohli být docela překvapení, protože
neobsahuje vůbec žádnou klauzuli GROUP BY. Mám k němu několik postřehů,
které se v praxi určitě budou nejdednou hodit:
- Agregační funkce lze použít i bez klauzule GROUP BY. V takovém
případě je za "skupinu" považována celá tabulka.
- Při výpočtu, v němž dělíme počtem řádků musíme být opatrní.
Snadno se můžeme dostat k chybám typu dělení nulou.
- Při výpočtu průměrných hodnot lze použít agregační funkci AVG
(průměr), díky čemuž se vyhneme použití SUM a COUNT.
Náš dotaz by tedy šel mnohem elegantněji a se stejnými výsledky
přepsat jako:
select avg(plat) from
pracovnik;
Jenomže pro nás by teď bylo mnohem přesnější znám průměrný plat v jednotlivých odděleních. K tomu
zcela jistě může posloužit dvojice dotazů s WHERE, takže při použití
obou výše popsaných variant dostáváme něco ve smyslu:
select avg(plat) from
pracovnik where oddeleni='marketing';
select avg(plat) from pracovnik where oddeleni='výroba';
případně
select sum(plat)/count(*) from pracovnik where oddeleni='marketing';
select sum(plat)/count(*) from pracovnik where oddeleni='výroba';
ale tento přístup má dvě podstatné nevýhody. Jednak je závislý na
tom, že známe názvy oddělení a jednak při vyšším počtu oddělení je
potřeba psát řadu dotazů. Jak asi tušíte, tohle není to pravé ořechové,
takže použijeme agregační funkci a sestavíme dotaz ve smyslu:
select oddeleni,
avg(plat) from pracovnik group by oddeleni;
Tím tedy víme, jaký je průměrný plat v každém oddělení, a tento
dotaz bude fungovat bez ohledu na počet oddělení a bez ohledu na počet
pracovníků v nich.
Klauzule HAVING
Kdybychom chtěli vypsat seznam všech oddělení, kde průměrný plat je
vyšší než průměrný plat v celé firmě, znalosti, které zatím máme nám
nestačí. My totiž potřebujeme
- nejprve zjistit průměrný plat na oddělení (což již umíme)
- pak z těchto průměrných platů vybrat ty, které jsou nadprůměrné
vzhledem k celé firmě. Nezapomeňme, že seznam oddělení nemusí obsahovat
jen dvě položky, ale že jich může být mnohem víc
Takže, jak to celé provést? Existuje klauzule příkazu SELECT, která
seskupené záznamy vytřídí. Je to HAVING. Náš příklad by tedy šel zapsat
takto:
select oddeleni,
avg(plat) from pracovnik group by oddeleni having avg(plat)>(select
avg(plat) from pracovnik);
Všimněte si dvou věcí - jednak nám tento příkaz vybral již seskupené
záznamy. V klauzuli HAVING tedy můžete bez obav používat agregační
funkce. Respektive měli byste, protože není-li v klauzuli HAVING
použita agregační funkce, dá se přepsat s použitím WHERE. A za druhé,
dnes poprvé jsme použili v příkazu SQL takzvaný poddotaz - "vnořený"
dotaz, který nějak souvisí s "hlavním" dotazem. O poddotazech ještě
bude řeč; tady byl uveden proto, že počítal průměrný plat v celé firmě.
Pozn.: Vybrat z každého oddělení jen
pracovníky s nadprůměrným platem (vzhledem k oddělení) lze sice také,
ale tento dotaz je zatím příliš složitý, než abychom jej tady uváděli.
Takže vydržte, ještě k tomu dojde.
Rozšíření ROLLUP
Když počítáte součty, může se Vám občas hodit dotaz, který vrací
kromě součtů i totály, tedy celkový součet všech mezisoučtů. Mějme
například dotaz, který na základě dat z minulého dílu počítá dobu
strávenou na jednotlivých stránkách podle prohlížečů:
select prohlizec,
sum(doba_prohlizeni) from logtable group by prohlizec;
Malou modifikací dosáhneme toho, že kromě řádků s jednotlivými
prohlížeči bude ve výsledné sadě záznamů i celkový součet:
select prohlizec,
sum(doba_prohlizeni) from logtable group by prohlizec with rollup;
není to však tak užitečné, jak by se na první pohled mohlo zdát.
Jednak toto rozšíření funguje až od verze 4.1.1 databáze MySQL. Ve
volající aplikaci navíc budete muset tento řádek s celkovými součty
nějak zpracovat. A konečně, mnoho aplikací a nástrojů pro zobrazování
dat (reporty, například) má stejně vlastní nástroje pro vytváření
celkových součtů.
Shrnutí
Příště již opustíme popis příkazu SELECT. Jak sami vidíte, je to
velmi složitý a komplikovaný příkaz, který nám sice umožňuje z databáze
vybrat prakticky cokoli, na druhou stranu je však náročný na
zapamatování. Jednotlivé klauzule tohoto příkazu tedy fungují v tomto
pořadí:
- SELECT
- FROM
- JOIN
- WHERE
- GROUP BY
- HAVING
- ORDER BY
I nadále budeme v seriálu průběžně používat příkaz SELECT. Je to
jediná cesta, jak jej dostat do krve. Konec konců, vybírání záznamů z
databáze je tou nejčastější činností, která vás při práci s DBMS čeká.
Verze pro tisk
|
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|
Vyhledávání software
Vyhledávání článků
28.11.2018 23:56 /František Kučera Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1
12.11.2018 21:28 /Redakce Linuxsoft.cz 22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář
6.11.2018 2:04 /František Kučera Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
4.10.2018 21:30 /Ondřej Čečák LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář
18.9.2018 23:30 /František Kučera Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
9.9.2018 14:15 /Redakce Linuxsoft.cz 20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business.
Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář
12.8.2018 16:58 /František Kučera Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář
16.7.2018 1:05 /František Kučera Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář
Více ...
Přidat zprávičku
Poslední diskuze
31.7.2023 14:13 /
Linda Graham iPhone Services
30.11.2022 9:32 /
Kyle McDermott Hosting download unavailable
13.12.2018 10:57 /
Jan Mareš Re: zavináč
2.12.2018 23:56 /
František Kučera Sraz
5.10.2018 17:12 /
Jakub Kuljovsky Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?
Více ...
|