Давайте взглянем на нашу таблицу телефонов и разобьем ее на группы по cityid, я специально поставил пробелы между группами:
+---------+-----------+-----------+-----------+--------+ | phoneid | firstname | lastname | phone | cityid | +---------+-----------+-----------+-----------+--------+ | 1 | John | Doe | 4144122 | 1 | | 2 | Steve | Doe | 414124 | 1 | | 3 | Johnatan | Something | 4142947 | 2 | | 4 | Donald | Trump | 414251123 | 2 | | 5 | Alice | Cooper | 414254234 | 2 | | 6 | Michael | Jackson | 4142544 | 3 | | 7 | John | Abama | 414254422 | 3 | | 8 | Andre | Jackson | 414254422 | 3 | | 9 | Mark | Oh | 414254422 | NULL | | 10 | Charly | Lownoise | 414254422 | NULL | | 12 | Mike | NULL | 1492823 | NULL | | 13 | Mike | NULL | 1492823 | NULL | +---------+-----------+-----------+-----------+--------+
Как найти количество записей для каждой из групп? Вот для этой задачи идеально подходит группировка – получить результат, сгруппировав его по определенной колонке:
SELECT CityId, count(*) FROM phone GROUP BY cityid;
Прочитаю, что я тут написал: выбрать id города и количество из таблицы телефонов, сгруппировав данные по cityid.
Сразу посмотрим на результат:
+--------+----------+ | CityId | count(*) | +--------+----------+ | NULL | 4 | | 1 | 2 | | 2 | 3 | | 3 | 3 | +--------+----------+
Как видите наш результате четко совпадает с тем, как мы разделили на группы нашу таблицу телефонов. Первая колонка – это id города, а вторая количество.
Слова GROUP BY должны идти в конце (только сортировка может идти после этого). После group by мы указываем, по какой колонке мы строим группы.
Тут очень важно понимать, что в SELECT мы можем указывать только колонки, по которым мы группируем или колонки, по которым мы считаем. В данном случае выводиться колонка cityid – по которой мы группируем и колонка с count. Можно также считать суммы по группе, минимум, максимум и т.д, то есть любые агрегатные функции.
Но мы не можем в SELECT указывать просто колонки, которые не участвуют в группе и не участвуют в агрегатной функции. Например:
SELECT CityId, FirstName, count(*) FROM phone GROUP BY cityid;
Такой запрос закончится ошибкой, потому что мы разбиваем данные на группы по городу, но просим вывести также и имя. Серверу просто срывает крышу в такой момент – какое из имен вывести, ведь в Торонто (cityid = 1) аж два имени John и Steve. Какое из них? Мы должны как-то четко сказать, какое из них нужно выбирать.
Можно сказать, что выбирай максимальное имя MAX:
SELECT CityId, max(FirstName), count(*) FROM phone GROUP BY cityid;
Теперь с точки зрения правил все верно – мы выбираем только город, по которому группируем и агригатные функции. И да, если у тебя возник вопрос – можно ли выполнять MAX на строках – можно. Строки сортируются по алфавиту и будет взято имя, которое идет последним – максимальное.
+--------+----------------+----------+ | CityId | max(FirstName) | count(*) | +--------+----------------+----------+ | NULL | Mike | 4 | | 1 | Steve | 2 | | 2 | Johnatan | 3 | | 3 | Michael | 3 | +--------+----------------+----------+