Tabela gory zawiera informacje o polskich szczytach oraz pasmach górskich, w których te szczyty się znajdują. Aby wyświetlić liczbę szczytów zapisanych w tabeli dla każdego pasma górskiego, należy wydać kwerendę
A.
SELECT pasmo, COUNT(*) FROM gory;
B.
SELECT pasmo, COUNT(*) FROM gory GROUP BY pasmo;
C.
SELECT COUNT(pasmo) FROM gory;
D.
SELECT pasmo, COUNT(*) FROM gory GROUP BY szczyt;
Zapytanie SELECT pasmo, COUNT(*) FROM gory GROUP BY pasmo; jest właściwe, bo łączy dwie bardzo ważne rzeczy w SQL: grupowanie rekordów i funkcję agregującą. Kolumna pasmo określa, do jakiego pasma górskiego należy dany szczyt, więc jeśli chcemy policzyć szczyty osobno dla Tatr, Beskidów czy Karkonoszy, trzeba pogrupować dane właśnie po tej kolumnie. GROUP BY pasmo tworzy osobne grupy rekordów dla każdej wartości w kolumnie pasmo, a COUNT(*) zlicza liczbę wierszy w każdej z tych grup. W praktyce wynik będzie czymś w rodzaju: Tatry – 5, Beskid Żywiecki – 3, Karkonosze – 4, zależnie od danych w tabeli. Moim zdaniem warto od razu wyrabiać sobie dobry nawyk dodawania aliasu, np. SELECT pasmo, COUNT(*) AS liczba_szczytow FROM gory GROUP BY pasmo;, bo wtedy wynik jest czytelniejszy dla użytkownika i łatwiejszy do wykorzystania w aplikacji. Zgodnie ze standardowym podejściem SQL każda kolumna w SELECT, która nie jest agregowana, powinna znaleźć się w GROUP BY. To jest ważna zasada, bo inaczej baza nie wie jednoznacznie, jaką wartość pokazać dla całej grupy. Takie zapytania stosuje się często w raportach, statystykach, panelach administracyjnych i zestawieniach, np. liczba produktów w kategoriach, liczba uczniów w klasach albo liczba zamówień według statusu.
W tym zadaniu kluczowe jest zrozumienie, że samo użycie COUNT(*) albo COUNT(pasmo) jeszcze nie oznacza zliczania osobno dla każdego pasma. Funkcja agregująca liczy dane, ale dopiero GROUP BY decyduje, według jakiego kryterium mają powstać grupy. Jeśli w zapytaniu pojawia się SELECT pasmo, COUNT(*) FROM gory; bez grupowania, to miesza się zwykłą kolumnę z agregacją dla całej tabeli. W standardowym SQL takie zapytanie jest niepoprawne, bo pasmo nie jest ani agregowane, ani wskazane w GROUP BY. Niektóre systemy baz danych, zwłaszcza przy luźniejszych ustawieniach, mogą coś zwrócić, ale wynik będzie logicznie podejrzany, bo jedna wartość pasma nie opisuje wszystkich wierszy tabeli. COUNT(pasmo) FROM gory też nie rozwiązuje problemu, ponieważ zwraca jedną liczbę dla całej tabeli, i to liczy tylko niepuste wartości kolumny pasmo. Nie pokazuje nazw pasm ani rozbicia na grupy, więc nie spełnia treści polecenia. Częsty błąd polega na tym, że ktoś widzi słowo COUNT i zakłada, że baza sama domyśli się, co ma liczyć osobno. SQL tak nie działa, trzeba mu jasno wskazać kryterium grupowania. Grupowanie po kolumnie szczyt również prowadzi w złą stronę, bo wtedy grupy powstają dla nazw szczytów, a nie dla pasm górskich. Jeśli każdy szczyt ma inną nazwę, COUNT(*) najczęściej da wartości 1, czyli zupełnie nie taki raport, jakiego oczekujemy. Dodatkowo wyświetlanie pasmo przy GROUP BY szczyt jest problematyczne według dobrych praktyk, bo kolumna pasmo nie jest częścią grupowania ani agregacji. Poprawne myślenie jest takie: chcę wynik dla każdego pasma, więc grupuję po pasmo; chcę policzyć rekordy w każdej grupie, więc używam COUNT(*).