MySQL GROUP BY and HAVING - Aggregation Reports Tutorial
Quick Answer
In MySQL, the GROUP BY clause groups rows sharing common values into summary rows, often used with aggregation functions like COUNT or SUM. The HAVING clause filters these grouped results based on aggregate conditions, enabling refined aggregation reports beyond WHERE clause capabilities.
Learning Objectives
- Understand the purpose and syntax of the GROUP BY clause in MySQL.
- Learn how to use HAVING to filter aggregated groups.
- Create practical aggregation reports using GROUP BY and HAVING.
Introduction
Aggregation reports summarize data by grouping rows and calculating aggregate values like totals or averages.
MySQL provides the GROUP BY clause to group rows and the HAVING clause to filter these groups based on aggregate conditions.
Understanding these clauses is essential for creating meaningful reports and insights from your data.
Group data to see the bigger picture, filter groups to focus on what matters.
Understanding GROUP BY Clause
The GROUP BY clause groups rows that have the same values in specified columns into summary rows.
It is commonly used with aggregate functions such as COUNT, SUM, AVG, MAX, and MIN to calculate summary statistics for each group.
- Syntax: SELECT columns, aggregate_function(column) FROM table GROUP BY columns;
- Groups rows sharing the same values in the GROUP BY columns.
- Aggregate functions compute summary values per group.
Example of GROUP BY
Consider a sales table with columns: product_id, quantity, and price.
To find total quantity sold per product, use GROUP BY on product_id with SUM aggregation.
Filtering Groups with HAVING Clause
The HAVING clause filters groups created by GROUP BY based on conditions involving aggregate functions.
Unlike WHERE, which filters rows before grouping, HAVING filters after aggregation.
- Syntax: SELECT columns, aggregate_function(column) FROM table GROUP BY columns HAVING condition;
- Use HAVING to filter groups by aggregate values, e.g., groups with total sales > 1000.
- HAVING can use aggregate functions in its conditions.
Example of HAVING
Continuing the sales example, to find products with total quantity sold greater than 100, add HAVING SUM(quantity) > 100.
Practical Aggregation Report Example
Let's create a report showing customers with more than 5 orders and their average order value.
This requires grouping orders by customer_id, counting orders, calculating average order value, and filtering groups.
SQL Query Example
The following query groups orders by customer_id, counts orders, calculates average total, and filters customers with more than 5 orders.
Practical Example
This query groups orders by customer_id, counts the number of orders per customer, calculates the average order value, and returns only customers with more than 5 orders.
Examples
SELECT customer_id, COUNT(*) AS order_count, AVG(total_amount) AS avg_order_value
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > 5;This query groups orders by customer_id, counts the number of orders per customer, calculates the average order value, and returns only customers with more than 5 orders.
Best Practices
- Always include all non-aggregated columns in the GROUP BY clause.
- Use HAVING only to filter aggregated groups, not individual rows.
- Test queries with small datasets to verify grouping and filtering logic.
- Use meaningful aliases for aggregated columns for readability.
- Avoid using HAVING without GROUP BY as it filters aggregated results.
Common Mistakes
- Using WHERE to filter aggregated results instead of HAVING.
- Not including all non-aggregated selected columns in GROUP BY.
- Confusing HAVING and WHERE clause purposes.
- Applying aggregate functions in WHERE clause, which is invalid.
- Forgetting to alias aggregated columns for clarity.
Hands-on Exercise
Create a Sales Summary Report
Write a query to show total sales and number of orders per product, filtering products with total sales above 500.
Expected output: A list of product_ids with total sales > 500 and their order counts.
Hint: Use GROUP BY product_id, SUM for total sales, COUNT for orders, and HAVING to filter.
Filter Customers by Average Order Value
Write a query to find customers whose average order value exceeds 100.
Expected output: Customer IDs with average order value greater than 100.
Hint: Group by customer_id, use AVG on order total, and HAVING to filter.
Interview Questions
What is the difference between WHERE and HAVING clauses in MySQL?
InterviewWHERE filters rows before grouping and cannot use aggregate functions, while HAVING filters groups after aggregation and can use aggregate functions.
Can you use HAVING without GROUP BY?
InterviewYes, HAVING can be used without GROUP BY to filter aggregated results over the entire result set.
Why do you need to include columns in GROUP BY?
InterviewColumns in the SELECT list that are not aggregated must be included in GROUP BY to define how rows are grouped.
MCQ Quiz
1. What is the best first step when learning Aggregation Reports?
A. Understand the purpose and basic idea
B. Skip directly to advanced implementation
C. Ignore examples and practice
D. Memorize terms without context
Correct answer: A
Starting with the purpose and basic idea makes later examples and practice easier to understand.
2. Which activity helps reinforce Aggregation Reports?
A. Reading once without practice
B. Building or writing a small practical example
C. Avoiding review questions
D. Skipping the summary
Correct answer: B
A small practical example helps connect the topic to real usage.
3. Which statement is most accurate about this topic?
A. In MySQL, the GROUP BY clause groups rows sharing common values into summary rows, often used with aggregation functions like COUNT or SUM.
B. Aggregation Reports never needs examples
C. Aggregation Reports is unrelated to practical work
D. Aggregation Reports should be learned without checking results
Correct answer: A
The correct option is based on the available topic explanation.
Key Takeaways
- GROUP BY groups rows sharing common column values for aggregation.
- HAVING filters groups based on aggregate conditions, unlike WHERE which filters rows before grouping.
- Aggregation functions like COUNT, SUM, AVG are essential for summarizing grouped data.
- Use HAVING to filter results after aggregation is performed.
- Combining GROUP BY and HAVING enables powerful reporting queries in MySQL.
Summary
The GROUP BY clause in MySQL groups rows sharing common values to enable aggregation.
HAVING filters these grouped results based on aggregate conditions, allowing refined reporting.
Together, GROUP BY and HAVING empower you to create powerful aggregation reports for data analysis.
Frequently Asked Questions
Can I use aggregate functions without GROUP BY?
Yes, aggregate functions can be used without GROUP BY to compute a summary over the entire table.
What happens if I omit HAVING when filtering aggregated data?
You cannot filter aggregated data with WHERE; omitting HAVING means you cannot filter groups based on aggregate values.
Is HAVING slower than WHERE?
HAVING is generally slower because it filters after aggregation, which can be more resource-intensive than WHERE filtering before aggregation.





