LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> 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 33028×

Komerční sdělení: Pořádáme Kurzy MySQL

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:

  1. Agregační funkce lze použít i bez klauzule GROUP BY. V takovém případě je za "skupinu" považována celá tabulka.
  2. 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.
  3. 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

  1. nejprve zjistit průměrný plat na oddělení (což již umíme)
  2. 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

pridej.cz

 

DISKUZE

Zaměstnanci s nejvyššími platy 24.10.2009 22:08 Jaroslav Sobota
  L Re: Zaměstnanci s nejvyššími platy 25.10.2009 00:40 Aleš Hakl




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

13.9.2017 8:00 /František Kučera

Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).


Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

15.4.2017 15:20 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě IoT a radiokomunikace? Přijď na sraz spolku OpenAlt, který se bude konat ve středu 19. dubna od 18:30 v Šenkovně (Sokolská 60, Praha 2).
Přidat komentář

5.3.2017 19:12 /Redakce Linuxsoft.cz
PR: 23. března proběhne v Praze konferenci na téma Cloud computing v praxi. Hlavními tématy jsou: Nejžhavější trendy v oblasti cloudu a cloudových řešení, Moderní cloudové služby, Infrastruktura současných cloudů, Efektivní využití cloudu, Nástrahy cloudových řešení a jak se jim vyhnout.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze