5 Grupowanie i sortowanie

background image

GROUP BY, HAVING

Dla potrzeb przykładółw utworzymy tablicę danych osobowych uczniów z różnych miast w
Polsce.

+------------------------------------------------------------------+

| Imię Nazwisko Miasto Data_urodzenia Telefon Płeć |

+------------------------------------------------------------------+

| Jan Łukomski Warszawa 1990-12-10 826-44-56 M |

| Anna Wierzbicka Kraków 1987-2-21 621-66-10 K |

| ... ... ... ... ... ... |

+------------------------------------------------------------------+

Opcja

GROUP BY

Opcja grupujca w zdaniu

SELECT

Wstawia się ją do zdania

SELECT

po opcji

WHERE

(lub

po opcji

FROM

, jeśli

WHERE

nie użyto), ale przed

ORDER BY

.

Przykłady:

Załóżmy, że chcemy znaleźć liczby uczniów z poszczególnych miast. Np. liczbę uczniów z
Gdańska można uzyskać łatwo:

mysql> SELECT COUNT(*) FROM Uczniowie WHERE Miasto='Gdańsk';

+---+

| 1 |

+---+

Podobnie można zrobić dla Krakowa, Warszawy i innych miast. Gorzej jest, jeśli chcemy
dokonać zbiorczych obliczeń dla różnych miast, tj. mieć listę miast i przy każdym - liczbę
mieszkających w nim uczniów. Do rozwiązania tego zadania trzeba użyć innej opcji zdania

SELECT

-

GROUP BY

.

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto
ORDER BY 2 DESC;

+----------------------+

| Miasto | COUNT(*) |

+----------------------+

| Warszawa | 6 |

| Kraków | 3 |

| Gdynia | 2 |

| Bydgoszcz | 1 |

| Tykocin | 1 |

| Otwock | 1 |

| Szczecin | 1 |

+----------------------+

Opcja

GROUP BY

("grupuj wynik wg") pozwala użyć funkcji agregujących (

SUM, AVG,

MAX, MIN, COUNT

) nie do całej tabeli, ale do grup wierszy w tabeli wynikowej. Innymi

słowy:

GROUP BY

określa zakres działania funkcji np.

COUNT

- tu działa ona dla każdego

miasta niezależnie (podobnie jest dla innych funkcji agregujących). Bez opcji

GROUP BY

background image

funkcja

COUNT

, a także pozostałe funkcje agregujące, działają na całej tabeli (na wszystkich

wierszach). Dla każdej grupy, tu: dla każdego miasta,

GROUP BY

generuje jeden wiersz.

Jeśli, oprócz funkcji agregującej, poda się w zapytaniu także inne kolumny, ale nie użyje się
opcji

GROUP BY

, zostanie zasygnalizowany błąd.

Tak będzie np. w przypadku zapytania:

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie;

mysql> Błąd nr 1140:

Mieszanie funkcji grupowych (MIN(),MAX(),COUNT()...), bez określenia
grupowania.

Przy próbie jej wykonania wypisany zostanie komunikat o mieszaniu kolumn z funkcjami
agregującymi, niedopuszczalnym bez użycia

GROUP BY

. Jest to naturalne - nie bardzo

wiadomo jak należałoby wypisać (potraktować) wynik powyższego zapytania bez
grupowania wyników (które miasto i jaką liczbę podać).

Przykłady:

1. Wypisz listę miast, z liczbą uczennic z każdego miasta, uporządkowaną malejąco wg

liczby uczennic.

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Płeć='K'

GROUP BY Miasto ORDER BY 2 DESC;

2. Wypisz dla każdego miasta jego nazwę oraz datę urodzenia najmłodszej uczennicy.

mysql> SELECT Miasto, MAX(Data_ur) AS Data FROM Uczniowie

WHERE Płeć='K' GROUP BY Miasto;

3. Napisz zapytanie, z którego dostaniemy numery miesięcy, z liczbami uczniów, którzy

urodzili się w tym miesiącu, uporządkowaną malejąco wg liczby uczniów, a w obrębie
tej samej liczby urodzeń - wg numerów miesięcy, rosnąco. Kolumny mają być
zatytułowane 'Miesiąc' i 'Liczba_uczniów'.

mysql> SELECT MONTH(Data_urodzenia) AS Miesiąc, COUNT(*) AS
Liczba_uczniów FROM Uczniowie GROUP BY 1 ORDER BY 2 DESC, 1

ASC;

Załóżmy teraz, że chcemy wybrać tylko te miasta, z których pochodzą co najmniej dwie
uczennice. Możemy spróbować warunek wstawić do

WHERE

:

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Płeć='K'
AND COUNT(*) >= 2 GROUP BY Miasto ORDER BY 2 DESC;

mysql> Błąd nr 1111:

Próba wykonania zapytania daje błąd. Jest on naturalny: opcja

WHERE

określa warunki na

rekordy, a nie na wynik ich przeszukiwania (dopiero na podstawie tego wyniku można
określić, dla którego miasta liczba uczennic jest większa lub równa 2). Sprawę rozwiązuje
użycie opcji

HAVING

, będącej dodatkowym filtrem nakładanym na wynik działania

GROUP

BY

:

background image

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto
HAVING COUNT(*) >= 2 ORDER BY 2 DESC;

+----------------------+

| Miasto | COUNT(*) |

+----------------------+

| Warszawa | 6 |

| Kraków | 3 |

| Gdynia | 2 |

+----------------------+

Załóżmy teraz, że chcemy wybrać tylko te miasta, z których pochodzą co najmniej dwie
uczennice. Możemy spróbować warunek wstawić do WHERE:

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Płeć='K'
AND COUNT(*) >= 2 GROUP BY Miasto ORDER BY 2 DESC;

Błąd nr 1111:

Błędne użycie funkcji grupowych.

Próba wykonania zapytania daje błąd. Jest on naturalny: opcja WHERE określa warunki na
rekordy, a nie na wynik ich przeszukiwania (dopiero na podstawie tego wyniku można
określić, dla którego miasta liczba uczennic jest większa lub równa 2). Sprawę rozwiązuje
użycie opcji HAVING, będącej dodatkowym filtrem nakładanym na wynik działania GROUP
BY:

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto
HAVING COUNT(*) >= 2 ORDER BY 2 DESC;

+----------------------+

| Miasto | COUNT(*) |

+----------------------+

| Warszawa | 6 |

| Kraków | 3 |

| Gdynia | 2 |

+----------------------+

Gdyby chodziło o miasta, z których pochodzi tylko jeden uczeń, warunek w HAVING byłby
COUNT(*)=1.

Podstawowa różnica między WHERE i HAVING polega na tym, kiedy w procesie tworzenia
tabeli wynikowej opcje te są wykorzystywane. Otóż WHERE służy do określenia, które
wiersze z tabeli wybrać, HAVING zaś 'działa' na rezultacie wyboru (już po zastosowaniu
WHERE). Tę różnicę widać w zapytaniach.

Następne zapytanie

mysql> SELECT COUNT(*) FROM Uczniowie WHERE Miasto LIKE 'W%';
+----------+

| COUNT(*) |

+----------+

| 7 |

+----------+

background image

wykona się poprawnie (liczba uczniów mieszkających w miastach o nazwach zaczynających
się na literę W. WHERE wyszuka takie rekordy w tabeli Uczniowie). Błędne jest natomiast
natomiast:

mysql> SELECT COUNT(*) FROM Uczniowie HAVING Miasto LIKE

'W%';

Błąd nr 1054:

Nieznana kolumna.

Błąd - nieznana kolumna. W wyniku zrealizowanej selekcji - a na tym wyniku działa HAVING
- nie ma kolumny 'Miasto' jest tylko liczba rekordów w tabeli Uczniowie.

Natomiast dwa zapytania:

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie WHERE Miasto
LIKE 'W%' GROUP BY Miasto;

+----------------------+

| Miasto | COUNT(*) |

+----------------------+

| Warszawa | 6 |

| Wrocław | 1 |

+----------------------+

mysql> SELECT Miasto, COUNT(*) FROM Uczniowie GROUP BY Miasto
HAVING Miasto LIKE 'W%';

+----------------------+

| Miasto | COUNT(*) |

+----------------------+

| Warszawa | 6 |

| Wrocław | 1 |

+----------------------+

zwrócą ten sam wynik.

Kiedy nie używa się opcji GROUP BY, opcja HAVING działa identycznie jak opcja WHERE
(warunek wyboru rekordów można podać w WHERE lub w HAVING, z tym samym skutkiem
końcowym). Problem: którą z tych opcji - przy braku GROUP BY lub w przypadku, gdy obie
opcje można stosować np. do selekcji pojedynczych rekordów - wybrać? Zasadą ogólną jest:
jeśli coś można wyfiltrować za pomocą WHERE, należy kryterium wyboru podać w tej opcji.
HAVING należy używać tylko wtedy, gdy używa się opcji GROUP BY. Przyczyn tego
zalecenia jest kilka, a jedną z nich jest efektywność: kolumny wyfiltrowane za pomocą
WHERE nie biorą już udziału w przetwarzaniu opcji GROUP BY i HAVING i tym samym
ogólny czas realizacji zapytania skraca się.


Wyszukiwarka

Podobne podstrony:
4 sortowanie
Sortowanie cz 2 ppt
Indywidualne a grupowe podejmowanie decyzji 3
a dusza grupowa
Procesy grupowe
CECHY STRUKTUR ORGANIZACYJNYCH PRACA GRUPOWA 17 KWIETNIA[1]
Psychoterapia grupowa
Dukaczewska Nałęcz Zogniskowane wywiady grupowe2
Metoda grupowa, pedagogika opiekuńczo - wychowawcza
Procesy grupowe, Kulturoznawstwo UAM, Psychologiczne determinanty komunikacji kulturowej
Praca grupowa zach org, WZ-stuff, semestr 2, zachowania organizacyjne
Sortowanie listów
Zajęcia grupowe z podstaw obsługi komputera
Praca grupowa
algorytmy sortowanie
5 sortowanie log

więcej podobnych podstron