Język SQL to nie tylko genialne narzędzie pozwalające na manipulację danymi w bazie danych na stronie internetowej, ale także bardzo prosty sposób na wykonanie prostego sprawdzenia, czy pewne wartości zgadzają się z naszym stanem wiedzy. Oczywiście możliwe jest napisanie skryptu, który nam wszystko policzy, ale czy nie prościej jest stworzyć jedno zapytanie, które w bardzo czytelny sposób pokaże żądany zbiór danych? W dzisiejszym wpisie chciałbym pokazać właśnie jedno z takich przydatnych zapytań, pokazujące liczbę powtórzeń danej wartości w tabeli bazy danych.

Fotografia: mwin, CC-BY-SA.

SQL: Zliczanie unikalnych wartości pola tabeli.

Pomysł na dzisiejszy wpis leżał w mojej “skarbnicy pomysłów” już od dłuższego czasu, ale nie miał do tej pory szczęścia zostać “wylosowanym” do omówienia na blogu. Ostatnio jednak mój kolega miał problem z dodaniem wymagania UNIQUE do pola w tabeli jednej ze swoich baz danych. Po wprowadzeniu mnie w całość zagadnienia, ze względu na to, że tabela była już wypełniona danymi, zasugerowałem wykonanie zapytania zliczającego powtórzenia, żeby ocenić, czy udałoby się w jakiś sposób dostosować wartości tabeli tak, aby się nie powtarzały. Podyktowałem mu wspomniane zapytanie z pamięci, niestety jednak nie liczyło ono tego, co chcieliśmy otrzymać.

Szybko odpaliłem swojego phpMyAdmina [pomysł z oddzielnym okienkiem na zapytanie odświeżające zawartość głównej strony jest po prostu genialny] i okazało się, że zapytanie nie było wcale takie złe - po prostu nie wziąłem pod uwagę klauzuli GROUP BY. Dlatego też dzisiejszy wpis będzie swojego rodzaju referencją - “przypominaczem” zarówno dla mnie, mojego kolegi, jak też dla Was.

Rozważmy więc typową tabelę:

CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `createdBy` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `slug` varchar(255) NOT NULL,
  `description` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Załóżmy, że podobnie jak mój kolega mamy w tej tabeli już pokaźną ilość danych i chcąc identyfikować poszczególne artykuły [rekordy tabeli articles] z wykorzystaniem pola slug chcemy dodać do niego wymaganie UNIQUE. W tym momencie chciałbym też usprawiedliwić moje tłumaczenie słowa “constraint” jako “wymaganie” - to słowo wydaje mi się najbardziej odpowiednie, ale oczywiście dyskusja na ten temat jest otwarta. ;]

Zapytanie, które policzy ilość powtarzających się slugów w tej tabeli, sortując wyniki według liczby powtórzeń prezentuje się następująco:

SELECT `slug`, COUNT(id) AS `num`
FROM `articles`
GROUP BY `slug`
ORDER BY `num` DESC

W klauzuli SELECT pobieramy nazwę interesującego nas pola wraz z liczbą rekordów jemu odpowiadających. Cała magia tego zapytania polega na wykorzystaniu klauzuli GROUP BY, dzięki której otrzymujemy tylko jeden wynik dla jednej wartości pola slug. Klauzul FROM oraz ORDER BY pozwolę sobie nie komentować. ;]

Przydatna będzie na pewno także modyfikacja tego zapytania zliczająca ilość powtórzeń powyżej pewnej wartości. Aby uzyskać taki wariant należy wykorzystać towarzyszącą GROUP BY klauzulę HAVING [w tym przypadku pobierzemy wszystkie slugi z liczbą powtórzeń większą od 5]:

SELECT `slug`, COUNT(id) AS `num`
FROM `articles`
GROUP BY `slug`
HAVING `num` > 5
ORDER BY `num` DESC

W tym miejscu warto zaznaczyć, że wykorzystując tego typu notację HAVING musi znajdować się zaraz pod GROUP BY, inaczej serwer SQL zwróci nam błąd składni zapytania.

Mam nadzieję, że dzisiejszy wpis będzie Wam służył i w razie czego wrócicie do niego, kiedy tak, jak ja, zapomnicie fragmentu “takiego prostego zapytania”. ;] Do zobaczenia w kolejnym wpisie!