SQL Playground
TutorialsPlayground
SQL FormatterSQL MinifierSyntax ValidatorJSON to SQLCSV to SQLSQL to JSONER Diagram Generator
Daily ChallengeInterviewsCheat SheetBlog

© 2026 SQL Playground. Built for developers.

PrivacyTermsAboutRSS Feed
SQL Playground
TutorialsPlayground
SQL FormatterSQL MinifierSyntax ValidatorJSON to SQLCSV to SQLSQL to JSONER Diagram Generator
Daily ChallengeInterviewsCheat SheetBlog
Back to Blog
2026-01-18
5 min read

Ranking Data with SQL: RANK, DENSE_RANK, and ROW_NUMBER Explained

sqlwindow-functionsrankinganalyticsdata-analysis

"Who are our top 10 customers?" "What's the rank of each student in their class?" "Show me the 3 best-selling products per category."

These questions all require ranking data. SQL provides three powerful window functions for this, and choosing the right one matters.

Comparison of ROW_NUMBER, RANK, and DENSE_RANK with ties
Comparison of ROW_NUMBER, RANK, and DENSE_RANK with ties

The Three Ranking Functions

FunctionHandles TiesGaps After Ties
ROW_NUMBER()No - assigns unique numbersN/A
RANK()Yes - same rank for tiesYes - skips numbers
DENSE_RANK()Yes - same rank for tiesNo - consecutive

Let's see each in action.

Interactive Example: Student Scores

Interactive SQL
Loading...

Look at Bob and Charlie - both scored 90:

  • ROW_NUMBER: Bob=2, Charlie=3 (arbitrary order for ties)
  • RANK: Both=2, Diana=4 (gap after tie)
  • DENSE_RANK: Both=2, Diana=3 (no gap)

When to Use Each Function

ROW_NUMBER: Unique Numbering

Use when you need exactly one number per row, regardless of ties:

-- Pagination: Get rows 11-20
SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (ORDER BY created_at) as rn
  FROM posts
) WHERE rn BETWEEN 11 AND 20;

RANK: Competition-Style Ranking

Use for leaderboards where ties share rank but the next person "drops":

-- Olympic-style: Gold, Gold, Bronze (no Silver)
SELECT athlete, time,
  RANK() OVER (ORDER BY time) as place
FROM race_results;

DENSE_RANK: Consecutive Ranking

Use when you want no gaps in your ranking sequence:

-- Top 3 salary levels (might be more than 3 people)
SELECT * FROM (
  SELECT name, salary,
    DENSE_RANK() OVER (ORDER BY salary DESC) as salary_rank
  FROM employees
) WHERE salary_rank <= 3;

Ranking Within Groups: PARTITION BY

The real power comes when ranking within categories:

Interactive SQL
Loading...

Notice how ranking restarts at 1 for each department!

Top N Per Group Pattern

One of the most useful SQL patterns - get the top N items from each category:

Interactive SQL
Loading...

Practical Example: Sales Leaderboard

Interactive SQL
Loading...

Quick Reference Table

ScenarioBest Function
PaginationROW_NUMBER()
Leaderboard with gapsRANK()
Top N salary levelsDENSE_RANK()
Exactly N rows per groupROW_NUMBER()
Olympic medal rankingRANK()
Finding duplicatesROW_NUMBER()

Common Mistakes to Avoid

  1. Forgetting ORDER BY: Ranking without ORDER BY gives unpredictable results.

  2. Using RANK for pagination: If there are ties, you might get more rows than expected.

  3. Ignoring tie-breakers: Add secondary ORDER BY columns to control tie behavior:

    ROW_NUMBER() OVER (ORDER BY score DESC, created_at ASC)
    

Conclusion

  • ROW_NUMBER(): One unique number per row, perfect for pagination and deduplication.
  • RANK(): Ties share rank, gaps follow - ideal for competitions.
  • DENSE_RANK(): Ties share rank, no gaps - great for "top N levels" queries.

Add PARTITION BY to rank within groups, and you can solve almost any leaderboard or "top N per category" problem in a single query.

Share this article:

Related Articles

sqldata-analysis

Calculating Percentiles and Median in SQL

AVG tells you the mean, but what about median and percentiles? Learn how to calculate these essential statistics in SQL using window functions and clever tricks.

Read more
sqlwindow-functions

Mastering SQL LEAD and LAG Functions for Row Comparisons

Need to compare a row with its previous or next row? Learn how SQL's LEAD and LAG window functions let you access neighboring rows without complex self-joins.

Read more
sqlwindow-functions

SQL Window Frames: ROWS vs RANGE

Learn how ROWS and RANGE window frames change results, avoid hidden pitfalls, and build correct moving calculations with clear, runnable examples.

Read more
Previous

Mastering SQL LEAD and LAG Functions for Row Comparisons

Next

Removing Duplicate Rows in SQL: A Complete Guide

Comments

© 2026 SQL Playground. Built for developers.

PrivacyTermsAboutRSS Feed