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 BY — does 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 (…)
ROW_NUMBER() OVER (PARTITION BY colonna ORDER BY colonna2)Components:
PARTITION BY— defines the "groups" (likeGROUP BY, but the rows stay separate);ORDER BYinsideOVER(…)— 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
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):
| Function | Positions |
|---|---|
ROW_NUMBER | 1, 2, 3, 4 (always unique) |
RANK | 1, 1, 3, 4 (ties share a position, leaves "gaps") |
DENSE_RANK | 1, 1, 2, 3 (ties share a position, without gaps) |
Example: product ranking per category
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
-- 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
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.
Show hint
PARTITION BY category_id groups, ORDER BY price DESC orders within the group.
Solution available after 3 attempts
Review exercise
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.
Show hint
ROW_NUMBER is always unique within the partition.
Solution available after 3 attempts