What if you could instantly find the top winners in every group without endless manual work?
Why Top-N per group query in SQL? - Purpose & Use Cases
Imagine you have a huge list of sales data for many stores, and you want to find the top 3 best-selling products for each store. Doing this by hand means sorting and filtering each store's data separately, which is like flipping through thousands of pages to find just a few items.
Manually sorting and picking top items for each group is slow and tiring. It's easy to make mistakes, miss some data, or waste hours repeating the same steps for every group. This approach doesn't scale when data grows bigger.
The "Top-N per group query" lets you ask the database to automatically find the top items within each group in one simple command. It saves time, reduces errors, and handles large data smoothly.
Sort data by store and sales; then pick top 3 products per store manually.
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY store ORDER BY sales DESC) AS rank FROM sales_data) AS ranked_sales WHERE rank <= 3;This concept lets you quickly find the best items in each category or group, unlocking powerful insights from your data instantly.
A retail manager uses a Top-N per group query to instantly see the top 3 selling products in every store, helping decide what to stock more of next month.
Manual sorting per group is slow and error-prone.
Top-N per group query automates finding best items per category.
It saves time and works well even with large data sets.
Practice
ROW_NUMBER() OVER (PARTITION BY column ORDER BY column) clause do in a SQL query?Solution
Step 1: Understand ROW_NUMBER() function
ROW_NUMBER() assigns a unique sequential number to rows in the result set.Step 2: Understand PARTITION BY usage
PARTITION BY divides rows into groups, and ROW_NUMBER() restarts numbering for each group.Final Answer:
Assigns a unique rank number to each row within each group defined by the partition column. -> Option AQuick Check:
ROW_NUMBER() with PARTITION BY = unique rank per group [OK]
- Thinking ROW_NUMBER() counts total rows
- Confusing PARTITION BY with filtering
- Assuming it filters rows automatically
employees table?Solution
Step 1: Understand ROW_NUMBER() usage in subquery
ROW_NUMBER() must be used in a subquery or CTE to assign ranks before filtering.Step 2: Filter rows by rank in outer query
The outer query filters rows where the rank (rn) is 2 or less per department.Final Answer:
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn FROM employees) sub WHERE rn <= 2; -> Option AQuick Check:
Use subquery with ROW_NUMBER() and filter by rank [OK]
- Trying to filter ROW_NUMBER() directly in WHERE clause
- Using LIMIT with PARTITION BY (not valid syntax)
- Using TOP without proper partitioning
sales with columns region, salesperson, and amount, what will this query return?SELECT region, salesperson, amount FROM (SELECT region, salesperson, amount, ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS rn FROM sales) AS ranked WHERE rn = 1;
Solution
Step 1: Analyze ROW_NUMBER() with PARTITION BY region
Rows are grouped by region and ranked by amount descending, so rn=1 is highest amount per region.Step 2: Filter WHERE rn = 1
This keeps only the top-ranked row per region, i.e., the highest sale amount record.Final Answer:
The highest sale amount record for each region. -> Option CQuick Check:
ROW_NUMBER() = 1 per group returns top record [OK]
- Thinking it returns all rows sorted
- Confusing rn=1 with lowest amount
- Assuming amount = 1 filters rows
orders table:SELECT customer_id, order_id, order_date, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) AS rank FROM orders WHERE rank <= 3;
Solution
Step 1: Understand alias usage in WHERE clause
Aliases like 'rank' defined in SELECT cannot be used in WHERE clause directly because WHERE is evaluated before SELECT.Step 2: Correct approach using subquery or CTE
Use a subquery or CTE to assign ROW_NUMBER(), then filter on 'rank' in outer query.Final Answer:
You cannot filter on an alias in the WHERE clause directly. -> Option DQuick Check:
Filter on ROW_NUMBER() alias in outer query, not WHERE [OK]
- Using alias in WHERE clause directly
- Thinking ORDER BY DESC is invalid
- Adding unnecessary GROUP BY
products table with columns category, product_id, and price. You want to find the top 2 most expensive products per category, but if two products have the same price, include both even if it means more than 2 per category. Which query achieves this?Solution
Step 1: Understand difference between ROW_NUMBER(), RANK(), and DENSE_RANK()
ROW_NUMBER() assigns unique ranks, so ties get different numbers. RANK() assigns same rank to ties and skips ranks after. DENSE_RANK() assigns same rank to ties but no gaps.Step 2: Choose RANK() to include ties at second place
RANK() allows including all products tied at rank 2, possibly more than 2 rows per category.Final Answer:
Use RANK() partitioned by category ordered by price DESC and filter WHERE rank <= 2. -> Option BQuick Check:
RANK() includes ties with same rank [OK]
- Using ROW_NUMBER() excludes ties
- Using DENSE_RANK() includes ties but no gaps
- Using COUNT() is invalid for ranking
Ready to prove it?
Pass the test and this pattern moves unknown
