GROUP BY vs PARTITION BY in SQL
GROUP BY vs PARTITION BY in SQL — What's the Difference?
Both GROUP BY and PARTITION BY organize rows into groups — but they do fundamentally different things with those groups. Mixing them up is one of the most common points of confusion once you move past basic SQL.
๐ The Core Difference
GROUP BY collapses rows: multiple input rows become one output row per group. You lose the individual row-level detail.
PARTITION BY (used with window functions) keeps every row, but lets you calculate something "within" each group without collapsing anything.
๐งช GROUP BY in Action
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
Output: one row per department. If you had 50 employees across 5 departments, you get back exactly 5 rows.
๐งช PARTITION BY in Action
SELECT
employee_name,
department,
salary,
AVG(salary) OVER (PARTITION BY department) AS dept_avg_salary
FROM employees;
Output: all 50 employee rows, unchanged — but each row now also shows the average salary for its department, calculated "over" that partition. Nothing collapses.
๐ฏ Side-by-Side Comparison
| employee_name | department | salary | dept_avg_salary (PARTITION BY) |
|---|---|---|---|
| Alice | Engineering | 9000 | 8500 |
| Bob | Engineering | 8000 | 8500 |
| Carol | Sales | 7000 | 7000 |
With GROUP BY, you'd only get back "Engineering: 8500" and "Sales: 7000" — you'd lose Alice, Bob, and Carol's individual rows entirely.
๐ ️ When to Use Which
- Use GROUP BY when you want a summary — total sales per region, average order value per customer, count of orders per day.
- Use PARTITION BY when you need row-level detail alongside a group-level calculation — "show me each employee's salary next to their department average," "rank each product within its category," "show each order alongside the customer's running total."
๐ A Practical Combined Example
Finding each employee who earns above their department's average — this needs PARTITION BY specifically, because GROUP BY alone can't compare an individual row to a group aggregate in the same query without a subquery:
SELECT * FROM (
SELECT
employee_name,
department,
salary,
AVG(salary) OVER (PARTITION BY department) AS dept_avg
FROM employees
) t
WHERE salary > dept_avg;
⚠️ Common Mistakes
- Reaching for a self-join or subquery to compare a row to its group average, when PARTITION BY does it directly and more efficiently
- Trying to use GROUP BY when you actually need individual row detail preserved — realizing too late that your report lost row-level granularity
- Forgetting that PARTITION BY requires an OVER() clause — it only works alongside a window function, not as a standalone clause
๐ Related Posts
- SQL Window Functions Explained: ROW_NUMBER, RANK, LAG, LEAD
- SQL WHERE vs HAVING: When to Use Each
Comments
Post a Comment