Aggregations & GROUP BY
Collapsing many rows into one summary row per group — counts, sums, and averages — plus the HAVING clause that filters groups.
What it is
GROUP BY collapses rows sharing a value into one row per group, and aggregate functions (COUNT, SUM, AVG, MIN, MAX) compute a summary over each group's rows.
WHERE vs. HAVING
WHERE filters individual rows before grouping happens; HAVING filters groups after aggregation — HAVING COUNT(*) > 5 keeps only groups with more than 5 rows, something WHERE can't express since it runs before groups exist.
Common pitfall
Every column in SELECT that isn't inside an aggregate function must appear in GROUP BY — otherwise the database can't determine which of the group's many values to show for that column.
Where it shows up
"Top N per category," "average order value per customer," and dashboard-style summary queries are all GROUP BY plus an aggregate.
