Skip to main content
eLearner.app
Module 7 · Lesson 2 of 426/57 in the course~14 min
Module lessons (2/4)

Window functions: rankings and per-group calculations

A window function is a function that operates on a "group of rows" (the window) but — unlike GROUP BYdoes not reduce the number of rows: a value computed over the window is attached to each row of the final result.

It's the right tool for rankings, progressive numbering, percentages over a group total, and many other operations that are awkward or impossible with GROUP BY.

The syntax: function() OVER (…)

SQL
ROW_NUMBER() OVER (PARTITION BY colonna ORDER BY colonna2)

Components:

  • PARTITION BY — defines the "groups" (like GROUP BY, but the rows stay separate);
  • ORDER BY inside OVER(…) — defines the order within the partition.

OVER () (empty parentheses) means "the whole table as a single window". Useful for computations like "percentage of total".

Ranking functions

SQL
ROW_NUMBER() OVER (PARTITION BY p ORDER BY o)
RANK()       OVER (PARTITION BY p ORDER BY o)
DENSE_RANK() OVER (PARTITION BY p ORDER BY o)

Differences (with values 100, 100, 90, 80):

FunctionPositions
ROW_NUMBER1, 2, 3, 4 (always unique)
RANK1, 1, 3, 4 (ties share a position, leaves "gaps")
DENSE_RANK1, 1, 2, 3 (ties share a position, without gaps)

Example: product ranking per category

SQL
SELECT name,
       category_id,
       price,
       RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS rank
FROM   products
ORDER BY category_id, rank;

For each category_id the RANK restarts from 1 and orders by descending price: you get the ranking of products within each category, in one shot.

Progressive numbering

SQL
-- Progressive order number for each customer:
SELECT id,
       customer_id,
       ordered_at,
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY ordered_at) AS row_num
FROM   orders
ORDER BY customer_id, row_num;

Each customer's first order will have row_num = 1, the second 2, etc.

Try it

Exercise#sql.m7.l2.e1
Attempts: 0Loading…

For each product show name, category_id, price and rank (the ranking by descending price WITHIN the category; use RANK). Order by ascending category_id and ascending rank.

Loading editor…
Show hint

PARTITION BY category_id groups, ORDER BY price DESC orders within the group.

Solution available after 3 attempts

Review exercise

Exercise#sql.m7.l2.e2
Attempts: 0Loading…

For each order show id, customer_id, ordered_at and row_num (progressive ROW_NUMBER per customer, ordered by ascending ordered_at). Order by customer_id and row_num.

Loading editor…
Show hint

ROW_NUMBER is always unique within the partition.

Solution available after 3 attempts