Skip to content
Laviyx Learn

Try

SQL course menu

SQL PARTITION BY: Window Functions Per Group (vs GROUP BY)

Learn SQL PARTITION BY in window functions: calculate per-group totals, averages and ranks while keeping every row, compare it with GROUP BY, and combine PARTITION BY with ORDER BY.

Advanced6 min readUpdated
On this page

PARTITION BY divides rows into groups for a window function. The function is calculated separately inside each group, but, unlike GROUP BY, every row stays in the result. It is how you put a group's total, average or rank next to each individual row.

The example table#

namedepartmentsalary
AshaSales52000
RaviEngineering78000
MeeraEngineering81000
JohnMarketing46000
PriyaSales61000

Syntax#

SQL
function(...) OVER (PARTITION BY column1, column2, ...)

Group values on every row#

SQLRun
SELECT name, department, salary,
       SUM(salary) OVER (PARTITION BY department) AS dept_total,
       COUNT(*)    OVER (PARTITION BY department) AS dept_size
FROM employees
ORDER BY department, name;
Output
name  | department  | salary | dept_total | dept_size
------+-------------+--------+------------+----------
Meera | Engineering | 81000  | 159000     | 2
Ravi  | Engineering | 78000  | 159000     | 2
John  | Marketing   | 46000  | 46000      | 1
Asha  | Sales       | 52000  | 113000     | 2
Priya | Sales       | 61000  | 113000     | 2

Each row keeps its own salary and also shows the total and size of its department.

PARTITION BY vs GROUP BY#

GROUP BYPARTITION BY
Rows in resultone per groupall rows
Where it is writtenits own clauseinside OVER (...)
Can show individual columns?only grouped onesyes, any column
Typical usesummary reportscomparing each row with its group

You can even use several different partitions in one query, which GROUP BY cannot do.

Comparing each row with its group#

Who earns the most in their department, and how far below the top is everyone else?

SQLRun
SELECT name, department, salary,
       MAX(salary) OVER (PARTITION BY department) AS dept_max
FROM employees
ORDER BY department;
Output
name  | department  | salary | dept_max
------+-------------+--------+---------
Ravi  | Engineering | 78000  | 81000
Meera | Engineering | 81000  | 81000
John  | Marketing   | 46000  | 46000
Asha  | Sales       | 52000  | 61000
Priya | Sales       | 61000  | 61000

dept_max - salary would give the gap to the top earner in each team.

Shares within a group#

Each region's share of each month's revenue, using monthly_sales:

SQLRun
SELECT month, region, revenue,
       ROUND(100.0 * revenue / SUM(revenue) OVER (PARTITION BY month), 1) AS share
FROM monthly_sales
WHERE month IN ('2026-01', '2026-02')
ORDER BY month, region;
Output
month   | region | revenue | share
--------+--------+---------+------
2026-01 | North  | 120     | 57.1
2026-01 | South  | 90      | 42.9
2026-02 | North  | 150     | 62.5
2026-02 | South  | 90      | 37.5

The partition is the month, so the shares in each month add up to 100.

PARTITION BY with ORDER BY#

Adding ORDER BY inside OVER turns the calculation into a running one that restarts for each partition:

SQL
SUM(revenue) OVER (PARTITION BY region ORDER BY month) AS running_total

And ranking functions use both: PARTITION BY decides where numbering restarts, ORDER BY decides the order. See ROW_NUMBER and RANK.

Partitioning by several columns#

PARTITION BY region, EXTRACT(YEAR FROM month_date) creates a separate window for each region-and-year combination, just like grouping by two columns.

Common mistakes#

Practice#

Practice exercise

For every employee, show their name, department, salary, and their salary as a percentage of their department's total payroll, rounded to one decimal place.

Show hint

100.0 * salary / SUM(salary) OVER (PARTITION BY department).

Show solution
SQLRun
SELECT name, department, salary,
       ROUND(100.0 * salary / SUM(salary) OVER (PARTITION BY department), 1) AS pct_of_dept
FROM employees
ORDER BY department, salary DESC;
Output
name  | department  | salary | pct_of_dept
------+-------------+--------+------------
Meera | Engineering | 81000  | 50.9
Ravi  | Engineering | 78000  | 49.1
John  | Marketing   | 46000  | 100
Priya | Sales       | 61000  | 54
Asha  | Sales       | 52000  | 46

John is the only person in Marketing, so he accounts for 100% of it. Some databases display these as 54.0 and 100.0.

Key takeaway#

Finished this lesson?