It is a query that finds the top N rows for each group in a table, like the top 3 salespeople per region.
Click to reveal answer
beginner
Which SQL function is commonly used to assign ranks for Top-N per group queries?
The ROW_NUMBER() function assigns a unique rank number to each row within a group, helping to select the top N rows.
Click to reveal answer
intermediate
How do you limit results to the top 3 rows per group using ROW_NUMBER()?
Use ROW_NUMBER() OVER (PARTITION BY group_column ORDER BY sort_column DESC) and then filter WHERE row_number <= 3.
Click to reveal answer
intermediate
Why is PARTITION BY important in Top-N per group queries?
PARTITION BY divides the data into groups so the ranking function restarts for each group, allowing top N per group selection.
Click to reveal answer
intermediate
Can you use LIMIT or FETCH FIRST directly to get Top-N per group?
No, LIMIT or FETCH FIRST applies to the whole result set, not per group. You need ranking functions like ROW_NUMBER() for per group limits.
Click to reveal answer
Which SQL clause is used to restart row numbering for each group in a Top-N per group query?
AGROUP BY
BPARTITION BY
CORDER BY
DWHERE
✗ Incorrect
PARTITION BY divides rows into groups so ROW_NUMBER() restarts numbering for each group.
What does ROW_NUMBER() do in a Top-N per group query?
AAssigns a unique rank number to each row within its group
BCounts total rows in the table
CFilters rows based on a condition
DGroups rows by a column
✗ Incorrect
ROW_NUMBER() assigns a unique rank to each row within each group, useful for selecting top N.
How do you select the top 5 rows per group after using ROW_NUMBER()?
ALIMIT 5
BGROUP BY row_number
CWHERE row_number <= 5
DORDER BY row_number DESC
✗ Incorrect
Filtering with WHERE row_number <= 5 keeps only the top 5 rows per group.
Which of these is NOT a correct way to get Top-N per group in SQL?
AUsing LIMIT without partitioning
BUsing RANK() with PARTITION BY
CUsing DENSE_RANK() with PARTITION BY
DUsing ROW_NUMBER() with PARTITION BY
✗ Incorrect
LIMIT alone does not work per group; it limits the whole result set.
What is the purpose of ORDER BY inside ROW_NUMBER() OVER()?
ATo limit the number of rows returned
BTo group rows by a column
CTo filter rows after ranking
DTo define how rows are ranked within each group
✗ Incorrect
ORDER BY inside ROW_NUMBER() defines the ranking order within each group.
Explain how to write a SQL query to get the top 3 highest salaries per department.
Think about dividing data by department and ranking salaries.
You got /3 concepts.
Describe why LIMIT alone cannot be used to get Top-N per group in SQL.
Consider how LIMIT works on the entire query output.
You got /3 concepts.
Practice
(1/5)
1. What does the ROW_NUMBER() OVER (PARTITION BY column ORDER BY column) clause do in a SQL query?
easy
A. Assigns a unique rank number to each row within each group defined by the partition column.
B. Counts the total number of rows in the entire table.
C. Filters rows to only include those with the highest value in the column.
D. Joins two tables based on the partition column.
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 A
Quick Check:
ROW_NUMBER() with PARTITION BY = unique rank per group [OK]
Hint: ROW_NUMBER() with PARTITION BY ranks rows per group [OK]
Common Mistakes:
Thinking ROW_NUMBER() counts total rows
Confusing PARTITION BY with filtering
Assuming it filters rows automatically
2. Which of the following SQL queries correctly selects the top 2 highest salaries per department from an employees table?
easy
A. SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn FROM employees) sub WHERE rn <= 2;
B. SELECT * FROM employees ORDER BY salary DESC LIMIT 2 PARTITION BY department;
C. SELECT * FROM employees WHERE ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) <= 2;
D. SELECT TOP 2 * FROM employees PARTITION BY department ORDER BY salary DESC;
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 A
Quick Check:
Use subquery with ROW_NUMBER() and filter by rank [OK]
Hint: Use subquery with ROW_NUMBER() then filter by rank [OK]
Common Mistakes:
Trying to filter ROW_NUMBER() directly in WHERE clause
Using LIMIT with PARTITION BY (not valid syntax)
Using TOP without proper partitioning
3. Given the table 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;
medium
A. All sales records sorted by amount descending.
B. All sales records where amount equals 1.
C. The highest sale amount record for each region.
D. The lowest sale amount record for each region.
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 C
Quick Check:
ROW_NUMBER() = 1 per group returns top record [OK]
Hint: Filter WHERE rn=1 to get top record per group [OK]
Common Mistakes:
Thinking it returns all rows sorted
Confusing rn=1 with lowest amount
Assuming amount = 1 filters rows
4. Identify the error in this SQL query that tries to get the top 3 recent orders per customer from 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;
medium
A. Missing GROUP BY clause for customer_id.
B. ROW_NUMBER() cannot be used with PARTITION BY.
C. ORDER BY must be ascending, not descending.
D. You cannot filter on an alias in the WHERE clause directly.
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 D
Quick Check:
Filter on ROW_NUMBER() alias in outer query, not WHERE [OK]
Hint: Filter ROW_NUMBER() in outer query, not WHERE clause [OK]
Common Mistakes:
Using alias in WHERE clause directly
Thinking ORDER BY DESC is invalid
Adding unnecessary GROUP BY
5. You have a 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?
hard
A. Use ROW_NUMBER() partitioned by category ordered by price DESC and filter WHERE rn <= 2.
B. Use RANK() partitioned by category ordered by price DESC and filter WHERE rank <= 2.
C. Use DENSE_RANK() partitioned by category ordered by price ASC and filter WHERE dense_rank <= 2.
D. Use COUNT() partitioned by category ordered by price DESC and filter WHERE count <= 2.
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 B
Quick Check:
RANK() includes ties with same rank [OK]
Hint: Use RANK() to include ties in top N per group [OK]
Common Mistakes:
Using ROW_NUMBER() excludes ties
Using DENSE_RANK() includes ties but no gaps
Using COUNT() is invalid for ranking
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.