Dana jest tabela uczniowie o polach id, nazwisko, imie, klasa. Które zapytanie SQL wyświetli liczbę osób w poszczególnych klasach oraz nazwę klasy?
A.
SELECT COUNT(id), klasa FROM uczniowie ORDER BY klasa;
B.
SELECT SUM(id), klasa FROM uczniowie GROUP BY klasa;
C.
SELECT COUNT(id), klasa FROM uczniowie GROUP BY klasa;
D.
SELECT SUM(id), klasa FROM uczniowie ORDER BY klasa;
Pytanie z egzaminu CKE, czerwiec 2021 (arkusz E.14-SG-21.06).
Zapytanie SELECT COUNT(id), klasa FROM uczniowie GROUP BY klasa; jest właściwe, bo łączy funkcję agregującą COUNT z grupowaniem rekordów według pola klasa. COUNT(id) zlicza wiersze, w których kolumna id nie ma wartości NULL, a ponieważ id zwykle jest kluczem głównym, to w praktyce oznacza liczbę uczniów. Klauzula GROUP BY klasa sprawia, że baza nie liczy wszystkich uczniów razem, tylko tworzy osobną grupę dla każdej klasy, np. 1A, 1B, 2TI, i dla każdej z nich zwraca oddzielny wynik. To jest klasyczny wzorzec raportowy w SQL: wybieramy kolumnę grupującą oraz agregat, np. COUNT, SUM, AVG, MIN albo MAX. Z mojego doświadczenia warto też nadawać aliasy, bo wynik jest czytelniejszy: SELECT klasa, COUNT(id) AS liczba_uczniow FROM uczniowie GROUP BY klasa;. W praktyce takie zapytanie przydaje się do raportów w dzienniku elektronicznym, statystyk szkoły, list obecności albo szybkiego sprawdzenia, które klasy są najliczniejsze. Dobra praktyka SQL mówi, że jeśli w SELECT występuje zwykła kolumna obok funkcji agregującej, to ta kolumna powinna znaleźć się w GROUP BY. Dzięki temu wynik jest jednoznaczny i zgodny ze standardowym sposobem pracy relacyjnych baz danych.
W tym zadaniu łatwo pomylić dwa różne pojęcia: sortowanie wyników i grupowanie rekordów. ORDER BY służy wyłącznie do ustawienia kolejności wyświetlania danych, na przykład alfabetycznie według klasy. Nie tworzy jednak osobnych grup i nie powoduje, że COUNT zostanie policzony oddzielnie dla każdej klasy. Jeżeli w zapytaniu pojawia się COUNT(id) oraz jednocześnie kolumna klasa, ale nie ma GROUP BY klasa, to w wielu systemach bazodanowych jest to zapytanie niezgodne z zasadami agregacji. Niektóre konfiguracje MySQL mogą coś zwrócić, ale nazwa klasy może być wtedy przypadkowa albo zależna od ustawień serwera, więc nie jest to dobre ani bezpieczne rozwiązanie. Moim zdaniem to jeden z częstszych błędów na początku nauki SQL: ktoś widzi, że trzeba pokazać klasy w kolejności, więc wybiera ORDER BY, a tu tak naprawdę chodzi o zebranie wierszy w grupy. Drugi problem to użycie SUM(id). Funkcja SUM dodaje wartości liczbowe, więc policzyłaby sumę identyfikatorów uczniów w danej klasie, np. 3 + 7 + 12, a nie liczbę uczniów. Identyfikator rekordu nie jest wartością statystyczną opisującą klasę, tylko technicznym kluczem do rozróżniania wierszy. Dodawanie takich identyfikatorów nie ma sensu biznesowego. Poprawne podejście to użycie COUNT do zliczania rekordów oraz GROUP BY do podziału na klasy. Jeśli dodatkowo chcemy uporządkować wynik, można dopisać ORDER BY klasa na końcu, ale dopiero po poprawnym grupowaniu: SELECT klasa, COUNT(id) AS liczba_uczniow FROM uczniowie GROUP BY klasa ORDER BY klasa;.