Grouping Flow
Schema Context
orders samplejson
1| order_id | customer_id | status | total_amount |2|----------|-------------|----------|--------------|3| 1001 | 1 | paid | 49.99 |4| 1002 | 1 | shipped | 12.50 |5| 1003 | 3 | pending | 8.00 |users samplejson
1| user_id | email | is_active |2|---------|---------------------|-----------|3| 1 | [email protected] | true |4| 2 | [email protected] | false |5| 3 | [email protected] | true |Aggregate Functions
| Function | Returns | Example question |
|---|---|---|
| COUNT(*) | Number of rows | How many orders? |
| SUM(col) | Total of numeric column | Total revenue? |
| AVG(col) | Average value | Average order size? |
| MIN / MAX | Smallest / largest | Cheapest order? |
Total number of ordersjson
1SELECT COUNT(*) AS order_count FROM orders;Expected outputjson
1| order_count |2|---|3| 3 |Total and average order amountjson
1SELECT2 SUM(total_amount) AS revenue,3 AVG(total_amount) AS avg_order4FROM orders;GROUP BY
Orders per customerjson
1SELECT customer_id, COUNT(*) AS order_count2FROM orders3GROUP BY customer_id;Expected outputjson
1| customer_id | order_count |2|---|---|3| 1 | 2 |4| 3 | 1 |SELECT rule
Every column in SELECT must either be in
GROUP BY or wrapped in an aggregate. SELECT customer_id, order_id, COUNT(*) is invalid without grouping order_id.GROUP BY with JOIN
Revenue per user emailjson
1SELECT u.email, SUM(o.total_amount) AS total_spent2FROM users u3INNER JOIN orders o ON u.user_id = o.customer_id4GROUP BY u.email;Expected outputjson
1| email | total_spent |2|---|---|3| [email protected] | 62.49 |4| [email protected] | 8.00 |HAVING — Filter Groups
| Clause | Filters | Example |
|---|---|---|
| WHERE | Individual rows before grouping | WHERE status = 'paid' |
| HAVING | Groups after aggregation | HAVING COUNT(*) > 1 |
Customers with more than one orderjson
1SELECT customer_id, COUNT(*) AS order_count2FROM orders3GROUP BY customer_id4HAVING COUNT(*) > 1;Common Mistakes
- Non-aggregated columns missing from GROUP BY.
- Using WHERE on aggregate results — use HAVING instead.
- Confusing COUNT(*) with COUNT(column) when NULLs exist.
Practice Prompts
- Find the maximum single order amount.
- Count orders grouped by status.
- Which users spent more than $50 total? (JOIN + GROUP BY + HAVING)
Try These Tools
Continue Learning
Frequently Asked Questions
What is an aggregate function?
A function that collapses many rows into one value: COUNT, SUM, AVG, MIN, MAX.
When is GROUP BY required?
When SELECT mixes aggregate functions with non-aggregated columns — every selected column must be in GROUP BY or inside an aggregate.
What is the difference between WHERE and HAVING?
WHERE filters rows before grouping. HAVING filters groups after aggregation.
Does COUNT(*) count NULLs?
COUNT(*) counts all rows. COUNT(column) ignores NULL values in that column.
Can I GROUP BY multiple columns?
Yes. Rows are grouped by the combined values of all GROUP BY columns.