GROUP BY разбивает строки на группы по значению колонки и считает агрегат отдельно для каждой группы:
SELECT city, COUNT(*) AS cnt, AVG(age) AS avg_age FROM users GROUP BY city;
Результат — по одной строке на город с подсчётами. Правило: всё, что в SELECT не агрегат, должно быть в GROUP BY.
Чтобы отфильтровать сами группы (а не строки), используют HAVING — он работает после группировки, тогда как WHERE до неё:
SELECT city, COUNT(*) AS cnt FROM users GROUP BY city HAVING COUNT(*) > 1; -- только города, где больше одного человека
Запомните разницу: WHERE фильтрует строки до группировки, HAVING — группы после. Сочетание GROUP BY и агрегатов — это, по сути, сводные таблицы средствами SQL: продажи по месяцам, заказы по клиентам, средний чек по категориям.