Lessons › SQL › Deep Dive: Advanced Window Functions
SQL lesson
PERCENT_RANK() and CUME_DIST()
PERCENT_RANK and CUME_DIST are window functions - meaning they calculate across a set of rows without collapsing them into a single result - that tell you where each row stands relative to the whole group. PERCENT_RANK says how far up the ranking a row has climbed (0 at the very bottom, 1 at the top), while CUME_DIST says what fraction of the group scores at or below that row.
Try this lesson free →Example
Segmenting Retail Products with PERCENT_RANK() and CUME_DIST()
SELECT product_id, category, units_sold, ROUND(PERCENT_RANK() OVER (ORDER BY units_sold)::numeric, 4) AS pct_rank, ROUND(CUME_DIST() OVER (ORDER BY units_sold)::numeric, 4) AS cum_dist FROM products ORDER BY units_sold| product_id | category | units_sold | pct_rank | cum_dist |
|---|---|---|---|---|
| P006 | Beauty | 30 | 0.0 | 0.1429 |
| P004 | Home | 60 | 0.1667 | 0.2857 |
| P002 | Clothing | 95 | 0.3333 | 0.5714 |
| P005 | Clothing | 95 | 0.3333 | 0.5714 |
| P001 | Electronics | 120 | 0.6667 | 0.7143 |
| P007 | Fashion | 175 | 0.8333 | 0.8571 |
Step by step
- Run the query without ROUND so you can see what the unfiltered values look like.
SELECT product_id, category, units_sold, PERCENT_RANK, ROUND(CUME_DIST() OVER (ORDER BY units_sold)::numeric, 4) AS cum_dist FROM products ORDER BY units_sold; - ROUND rounds the value to the nearest integer (or to N decimal places with a second argument).
SELECT product_id, category, units_sold, ROUND(PERCENT_RANK() OVER (ORDER BY units_sold)::numeric, 4), ROUND(CUME_DIST() OVER (ORDER BY units_sold)::numeric, 4) AS cum_dist FROM products ORDER BY units_sold; - AS gives the ROUND result a friendly column name so the output reads cleanly.
SELECT product_id, category, units_sold, ROUND(PERCENT_RANK() OVER (ORDER BY units_sold)::numeric, 4) AS pct_rank, ROUND(CUME_DIST() OVER (ORDER BY units_sold)::numeric, 4) AS cum_dist FROM products ORDER BY units_sold;
Practice
1. Using orders, write a query that adds PERCENT_RANK() over revenue ascending to each row.
SELECT *, PERCENT_RANK() OVER (ORDER BY revenue) FROM orders2. Using store_sales, write a query that adds CUME_DIST() over revenue ascending to each row.
SELECT *, CUME_DIST() OVER (ORDER BY revenue) FROM store_sales3. Using products, write a query that adds CUME_DIST() over price ascending to each row.
SELECT *, CUME_DIST() OVER (ORDER BY price) FROM products4. Using employees, write a query that adds CUME_DIST() over salary ascending to each row.
SELECT *, CUME_DIST() OVER (ORDER BY salary) FROM employees5. Using reviews, write a query that adds CUME_DIST() over rating ascending to each row.
SELECT *, CUME_DIST() OVER (ORDER BY rating) FROM reviewsLearn it by doing. This lesson is a short hands-on level on Bampaa: see it work, then build and write it yourself, with instant feedback.
Try this lesson free →