Nejčastější SQL příkaz SELECT má kromě obvyklých komponent FROM, WHERE, ORDER BY a LIMIT také méně obvyklé části GROUP BY a HAVING. GROUP BY slouží k seskupení řádek do jedné skupiny podle daného kritéria, HAVING slouží k omezení skupin, které mají být vráceny. Vhodným použitím GROUP BY lze vytvořit elegantnější kód, HAVING jsem naproti tomu u webových aplikací v praxi použil jen zřídka. Seskupování se obvykle používá spolu s agregačními funkcemi.
Dejme tomu, že chceme vypsat všechny články spolu s počtem diskusních příspěvků, které se k nim vztahují, a datem posledního z nich.
<?php // neefektivní kód $result = mysql_query("SELECT id, nadpis FROM clanky"); while ($row = mysql_fetch_assoc($result)) { $pocet = mysql_result(mysql_query("SELECT COUNT(*) FROM diskuse WHERE clanek = '$row[id]'"), 0); $posledni = mysql_result(mysql_query("SELECT MAX(datum) FROM diskuse WHERE clanek = '$row[id]'"), 0); echo "<li><a href='?id=$row[id]'>$row[nadpis]</a> - diskuse: $pocet" . (isset($posledni) ? ", poslední: $posledni" : "") . "</li>\n"; } mysql_free_result($result); // s využitím GROUP BY $result = mysql_query(" SELECT clanky.id, clanky.nadpis, COUNT(diskuse.id) AS pocet, MAX(diskuse.datum) AS posledni FROM clanky LEFT JOIN diskuse ON clanky.id = diskuse.clanek GROUP BY clanky.id "); while ($row = mysql_fetch_assoc($result)) { echo "<li><a href='?id=$row[id]'>$row[nadpis]</a> - diskuse: $row[pocet]" . (isset($row["posledni"]) ? ", poslední: $row[posledni]" : "") . "</li>\n"; } mysql_free_result($result); ?>
První kód je neefektivní proto, že uvnitř cyklu se opakovaně kladou SQL dotazy, což je relativně pomalá operace. V kódu si všimněte podmínky vypisování data posledního příspěvku – pokud totiž žádný příspěvek do diskuse k článku ještě vložen nebyl, vrátí MAX hodnotu NULL, která je převedena na PHP hodnotu null.
Sluší se zmínit, že v SQL lze podle normy vybírat jen sloupce, podle kterých se seskupuje nebo na které je aplikována agregační funkce (tedy místo SELECT id, nazev … GROUP BY id
je nutné psát SELECT id, nazev … GROUP BY id, nazev
nebo SELECT id, MAX(nazev) … GROUP BY id
). MySQL tak přísné není a dovoluje vybírat jakékoliv sloupce, do kterých dosadí náhodnou hodnotu ze skupiny – pokud tedy seskupujeme podle unikátního klíče, můžeme se na správnou hodnotu sloupce spolehnout, v jiném případě je lepší se této zkratce vyhnout.
Od MySQL 4.1.1 je k dispozici modifikátor ROLLUP, který vy mně vyvolává dojem, že si ho někdo v MySQL zaplatil.
Přijďte si o tomto tématu popovídat na školení Návrh a používání MySQL databáze.
Diskuse je zrušena z důvodu spamu.