Where the author refers to one row per group in the GROUP BY
he is referring to the result set, then when referring to the rows per group in HAVING
he is referring to the input.
Imagine this simple data set
Col1 Col2 Value
----------------------
a a 1
a b 1
a b 1
a b 2
a c 1
a c 5
As you can see there are 3 different tuples for (Col1, Col2) -- (a, a), (a, b), (a, c), therefore if you GROUP BY Col1, Col2 you will get three rows in your result (One per group).
SELECT Col1, Col2
FROM T
GROUP BY Col1, Col2;
Gives
Col1 Col2
-------------
a a
a b
a c
This is what the author is referring to when saying "one row per group".
However, expanding again you can see that there are two rows with the tuple (a, b), and two for (a, c) - so there are two input rows for each, this is what the COUNT(*)
is referring to, not the number of rows in the result set.
Any aggregate functions (either in the having or in the select) are calculated at the same time as the GROUP BY, not at their respective parts (HAVING, SELECT). They are the same operation, this is how it maintains knowledge of the number of rows in the group before they are used in the select or having.
There is very good answer on Stackoverflow explaining how aggregates work behind the scenes for further reading, so I won't repeat it here.