Having
WHERE cannot work with aggregates, HAVING can.
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition
ORDER BY column_name(s);
(see: W3Schools and this stackoverflow).
So e.g. if we wanted, naively, to do
SELECT DISTINCT gid
FROM `gd`
WHERE COUNT(*) > 10 --- error
ORDER BY lastupdated DESC
this wouldn't work. This is where we need HAVING:
SELECT gid
FROM `gd`
GROUP BY gid
HAVING COUNT(*) > 10
ORDER BY lastupdated DESC
Essentially, WHERE happens before aggregation, whereas HAVING happens after aggregation.
See Order of Execution below.
Order of Execution
(See builtin.com).
These clauses are not evaluated in the order written, but rather in the order below.
Importantly, column aliases created in the SELECT cannot be referred to by the WHERE
and HAVING clauses.
FROM/JOINWHEREGROUP BYHAVINGSELECTORDER BYLIMIT/OFFSET