The ranking functions number each partition's rows in the window's ORDER BY and differ on ties. A view (Views) of units sold per product, reused below, has three titles tied at 3:
CREATE VIEW units_sold AS SELECT p.id, p.sku, p.category_id, SUM(i.quantity) AS units
FROM products AS p JOIN order_items AS i ON i.product_id = p.id
JOIN orders AS o ON o.id = i.order_id AND o.status <> 'cancelled' GROUP BY p.id;
SELECT category_id AS cat, sku, units, ROW_NUMBER() OVER (ORDER BY units DESC) AS row_num,
RANK() OVER (ORDER BY units DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY units DESC) AS dense,
RANK() OVER (PARTITION BY category_id ORDER BY units DESC) AS in_cat
FROM units_sold ORDER BY units DESC, row_num;Output
Query OK, 0 rows affected (0.013 sec) +-----+-----------+-------+---------+-----+-------+--------+ | cat | sku | units | row_num | rnk | dense | in_cat | +-----+-----------+-------+---------+-----+-------+--------+ | 5 | AC-MUG-01 | 6 | 1 | 1 | 1 | 1 | | 5 | AC-STK-01 | 4 | 2 | 2 | 2 | 2 | | 2 | BK-PHP-01 | 3 | 3 | 3 | 3 | 1 | | 3 | BK-SQL-01 | 3 | 4 | 3 | 3 | 1 | | 2 | BK-LAR-01 | 3 | 5 | 3 | 3 | 1 | | 2 | BK-LNX-01 | 2 | 6 | 6 | 4 | 3 | | 3 | BK-SQL-02 | 1 | 7 | 7 | 5 | 2 | +-----+-----------+-------+---------+-----+-------+--------+ 7 rows in set (0.001 sec)
ROW_NUMBER never repeats, so its order among ties is arbitrary unless you add a tiebreaker such as id. RANK shares a number and skips; DENSE_RANK shares without skipping. Wrap the query in a CTE and keep in_cat = 1, and you have the top product per category COUNT, SUM, AVG, MIN, and MAX could not write, both tied Programming titles included.