Quick answer
GROUP BY is used in SQL to combine rows that share the same value in one or more columns.
Once rows are grouped, you usually use aggregate functions like
COUNT(),
SUM(),
AVG(),
MIN(), or
MAX()
to summarize each group.
In beginner terms, GROUP BY answers questions like:
- How many employees are in each department?
- What is the average salary in each city?
- How much total revenue came from each product category?
GROUP BY.
In this guide
Sample table
To keep the examples simple, imagine this employees table:
| employee_id | name | department | salary | city |
|---|---|---|---|---|
| 1 | Ana | Sales | 62000 | Chicago |
| 2 | Ben | IT | 78000 | Dallas |
| 3 | Chris | HR | 56000 | Chicago |
| 4 | Dana | IT | 85000 | Denver |
| 5 | Evan | Sales | 59000 | Austin |
What GROUP BY does
GROUP BY takes rows that have the same value in a chosen column and puts them into buckets.
For example, if you group by department, all Sales rows go into one bucket, all IT rows go into one bucket, and all HR rows go into one bucket.
SELECT department FROM employees GROUP BY department;
That would return one row per department.
GROUP BY is not very exciting. The real power comes when you combine it with aggregate functions like COUNT(), SUM(), and AVG().
Count rows in each group
One of the most common uses of GROUP BY is counting how many rows fall into each category.
SELECT department, COUNT(*) AS employee_count FROM employees GROUP BY department;
This gives you one row per department, along with the number of employees in each department.
| department | employee_count |
|---|---|
| Sales | 2 |
| IT | 2 |
| HR | 1 |
Get totals for each group
You can also total numeric values within each group using SUM().
SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department;
This returns the total salary cost for each department.
| department | total_salary |
|---|---|
| Sales | 121000 |
| IT | 163000 |
| HR | 56000 |
SUM() is useful for totals such as revenue, quantity sold, hours worked, or salary expense.
Get averages for each group
Averages are another common use of grouped summaries.
SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department;
This shows the average salary in each department.
| department | avg_salary |
|---|---|
| Sales | 60500 |
| IT | 81500 |
| HR | 56000 |
COUNT(), SUM(), AVG(), MIN(), or MAX() depending on what you want to measure.
Group by multiple columns
You can group by more than one column if you want more specific buckets.
SELECT department, city, COUNT(*) AS employee_count FROM employees GROUP BY department, city;
This creates groups for each department-and-city combination instead of grouping only by department.
Using HAVING with GROUP BY
WHERE filters rows before grouping. HAVING filters grouped results after grouping.
SELECT department, COUNT(*) AS employee_count FROM employees GROUP BY department HAVING COUNT(*) > 1;
This returns only departments with more than one employee.
WHERE for row-level filtering. Use HAVING for group-level filtering after the grouped results already exist.
When to use GROUP BY
Use GROUP BY when you want one result per category instead of one big result for the whole table.
GROUP BY.
Common mistakes
- Using a normal column with an aggregate function without adding that normal column to
GROUP BY - Confusing
WHEREandHAVING - Grouping by too many columns and accidentally creating tiny buckets
- Forgetting that each group returns one summary row
- Using
GROUP BYwhen a normalSELECTwould have been enough
GROUP BY clause.
Practice questions
HAVING.
Bottom line
GROUP BY is one of the most important SQL skills because it lets you summarize data by category.
Once you understand how to group rows and apply aggregate functions, you can answer a huge number of real reporting and analysis questions.
Related SQL tutorials
Start here for all SQL topics and tutorials.
Learn COUNT, SUM, AVG, MIN, and MAX, which are commonly used with GROUP BY.
Learn how tables connect before grouping joined data together.
See how join types affect the rows you group and summarize.