
📎 This article includes 2 downloadable practice files ↓
If you can build a pivot table, you already understand GROUP BY. It is the SQL way to say “one row per region, with totals”.
In this article
The pivot-table equivalent
SELECT region, SUM(amount) AS total_sales, COUNT(*) AS orders
FROM sales
GROUP BY region
ORDER BY total_sales DESC;
Rows area = GROUP BY region; Values area = SUM(amount), COUNT(*).
Group by more than one column
SELECT region, product, SUM(amount) AS total
FROM sales
GROUP BY region, product;
WHERE vs HAVING
- WHERE filters rows before grouping (like a report filter).
- HAVING filters groups after grouping (like filtering the pivot’s totals).
SELECT customer, SUM(amount) AS total
FROM sales
WHERE order_date >= '2018-01-01' -- only this year's rows
GROUP BY customer
HAVING SUM(amount) > 100000; -- only big customers
Useful aggregates
| Function | Gives |
|---|---|
COUNT(*) |
Rows in the group |
COUNT(DISTINCT customer) |
Unique customers |
AVG(amount) |
Average |
MIN / MAX |
First/last date, smallest/largest value |
Practise these queries in the browser in the SQL Playground.
📎 Practice files for this article
⬇ Download all 2 files (ZIP · 7 KB)
- 📄SQLite practice databaseorders (400 rows) and monthly_sales tables for every query in the post.⬇ DB · 28 KB
- 🗃️GROUP BY / HAVING queries (.sql)The post's queries plus the classic 'not in GROUP BY' mistake.⬇ SQL · 516 B
Free to use for learning. Files with macros (.bas) are plain text — import them with Alt+F11 → File → Import File, and always test on a copy.
Atul (AJ) builds office-automation and local-first AI tools as Atulya AI, and works with Excel, SAP and Oracle EPM every day. He writes about the shortcuts, macros and automations that actually save time — plus the occasional wacky fact. Videos on YouTube: Lazy Automator AI (@LazyAutomatorAI).
More posts by Atul →Stuck on a step? Ask a question and the AI answers using this article.