GROUP BY aggregates rows that share common values into summary rows.
GROUP BY collapses rows with identical values in one or more columns and returns one summary row per group. Combine it with aggregate functions such as COUNT(), SUM(), AVG(), MIN(), or MAX() to produce totals and other metrics.
List the non-aggregated columns, add at least one aggregate, then append GROUP BY with the same non-aggregated columns.
SELECT customer_id, COUNT(*) AS order_count
FROM Orders
GROUP BY customer_id;
Use SUM(), COUNT(), AVG(), MIN(), MAX(), GROUP_CONCAT(), JSON_ARRAYAGG(), or user-defined aggregates. Pick the function that answers your business question, e.g., SUM(total_amount) for revenue.
Yes. Include every column that defines a unique group.
SELECT customer_id,
YEAR(order_date) AS yr,
SUM(total_amount) AS yearly_spend
FROM Orders
GROUP BY customer_id, YEAR(order_date);
HAVING evaluates after grouping, letting you keep or discard groups based on aggregate values.
SELECT customer_id,
SUM(total_amount) AS spend
FROM Orders
GROUP BY customer_id
HAVING SUM(total_amount) > 5000;
Add indexes to columns used in GROUP BY and WHERE. Filter early with WHERE, avoid unnecessary columns, and consider summary tables or materialized views for heavy reports.
SELECT c.id,
c.name,
SUM(o.total_amount) AS total_spent
FROM Customers AS c
JOIN Orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY total_spent DESC
LIMIT 10;
Avoid selecting columns not listed in GROUP BY when ONLY_FULL_GROUP_BY is enabled, and don’t place HAVING conditions that belong in WHERE, as this forces unnecessary grouping.
No. Use ORDER BY explicitly to control the output order. Without ORDER BY, MySQL may return groups in any sequence.
MySQL’s ONLY_FULL_GROUP_BY SQL mode demands that every selected column be aggregated or listed in GROUP BY. Adjust the SELECT list or GROUP BY clause to comply.
Use COUNT(DISTINCT column), e.g., COUNT(DISTINCT product_id) to count unique products per customer.