RANK()

Rank rows with tied values getting the same position — gaps after ties

Advanced 10 minRANKrankingwindow

RANK: Ties Get the Same Number

RANK() gives tied values the same rank, then skips numbers after the tie. If two items share rank 2, the next item gets rank 4 — there is no rank 3. Here's how it works:

Ties share a rank — When multiple rows have the same value in the ORDER BY column, they all receive the same rank number. Two items tied at rank 2 both get rank 2.
Gaps follow ties — After a tie, the next rank skips ahead. The skip size equals the number of tied items. If 3 items tie at rank 2, the next item gets rank 5 — ranks 3 and 4 are never assigned.
How it differs from ROW_NUMBER — ROW_NUMBER always assigns unique sequential numbers (1, 2, 3, 4) and breaks ties arbitrarily. RANK preserves ties: 1, 2, 2, 4. Use ROW_NUMBER when you need unique numbering; use RANK when ties should be visible.
When to use RANK — Choose RANK when ties are meaningful and the rank should reflect how many items are ahead. If 2 people tie for 2nd place, the next person is correctly ranked 4th — there is no 3rd place. This is competition-style ranking.
Knowledge Canvas

How RANK Works

Rank with gaps after ties

  • Tied values get the same rank
  • Next rank after a tie SKIPS: 1, 2, 2, 4
  • Gap = number of tied rows before it
  • PARTITION BY creates independent ranking groups

RANK vs ROW_NUMBER

Ties vs unique numbering

RANK: 1, 2, 2, 4
Ties share rank, gaps follow
ROW_NUMBER: 1, 2, 3, 4
Always unique, no ties

When to Use RANK

Gap behavior is sometimes what you want

  • Competition scoring: 2 silver medals → no bronze awarded
  • Leaderboards where position matters absolutely
  • Filtering: "top 3 ranks" may return 4+ rows with ties
  • Use ROW_NUMBER if you want exactly one row per rank

RANK Gotchas

Gaps cause surprises

  • WHERE rank <= 3 might return 2 rows (if rank jumps from 2 to 4)
  • Or it might return 4 rows (if rank 3 has ties)
  • Gaps make RANK unsuitable for "give me exactly N rows"
  • Use ROW_NUMBER for exact row counts
Syntax
Syntax Template
1-- Single ranking across all rows
2RANK() OVER (
3 ORDER BY score DESC
4) AS rnk
5
6-- Ranking that restarts per group
7RANK() OVER (
8 PARTITION BY category
9 ORDER BY price DESC
10) AS category_rank
RANK()Same rank for ties, gaps after: 1, 2, 2, 4
vs ROW_NUMBERROW_NUMBER never ties: 1, 2, 3, 4
Sample Data
reviews
12 rows
product_idrating
P1015
P1014
P1013
P1025
P1024
P1034
P1045
P1055
P1054
P1073
P1085
P1095
products
10 rows
idnamecategorypricestock
P101Wireless MouseElectronics24.99150
P102Office DeskFurniture18925
P103LED Desk LampFurniture45.580
P104USB-C CableElectronics12.99500
P105Bluetooth SpeakerElectronics7960
P106Office ChairFurniture9515
P107Coffee MakerAppliances89.9940
P108Notebook SetStationery8.5200
P109Wireless HeadphonesElectronics15930
P110Standing DeskFurniture4258

Worked Example

Rank products by their average rating, showing ties.

SQL
1WITH product_ratings AS (
2 SELECT
3 product_id,
4 ROUND(AVG(rating), 1) AS avg_rating
5 FROM reviews
6 GROUP BY
7 product_id
8)
9SELECT
10 p.name,
11 pr.avg_rating,
12 RANK() OVER (ORDER BY pr.avg_rating DESC) AS rnk
13FROM product_ratings pr
14JOIN products p
15 ON p.id = pr.product_id;
Products with identical average ratings get the same rank. After a tie, the next rank skips — if three products tie at rank 1, the next product is rank 4.
Output
5 rows
nameavg_ratingrnk
USB-C Cable51
Notebook Set51
Wireless Headphones51
Office Desk4.54
Bluetooth Speaker4.54

Key Concepts

1RANK: same rank for ties, then skip (1, 2, 2, 4)
2Gap size = number of tied items before the next rank
3Competition-style: 2 people tie for 2nd → next is 4th, not 3rd
4RANK vs ROW_NUMBER: ties matter vs unique numbering needed

Pro Tip

RANK gives competition-style rankings where ties share a position and subsequent ranks reflect the actual count of items ahead.

When to Use

Leaderboards, competition rankings, exam results, sales performance rankings.

Challenge

Solve the problem below

Rank all products by price (highest first). Show name, price, and rank. Use RANK().

Your Query