lesson 36 Window functions · advanced
RANK & DENSE_RANK
Rank rows and decide how ties should behave.
the idea
RANK and DENSE_RANK give equal values the same rank. After a tie, RANK skips positions (1, 2, 2, 4) and DENSE_RANK does not (1, 2, 2, 3). Aggregate first to the grain you want to rank, then apply the window.
Dataset: Sports
The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.
games13 columns · 23,168 rows
| game_idtext · unique id | seasonnumber · links to seasons | game_datedate | game_numbernumber | game_typetext | venue_idtext · links to venues | home_team_idtext · links to teams | away_team_idtext · links to teams | home_scorenumber | away_scorenumber | day_nighttext | attendancenumber | duration_minutesnumber |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ANA201604040 | 2016 | 2016-04-04 | 0 | regular | ANA01 | ANA | CHN | 0 | 9 | night | 44020 | 188 |
| ANA201604050 | 2016 | 2016-04-05 | 0 | regular | ANA01 | ANA | CHN | 1 | 6 | night | 37042 | 154 |
| ANA201604070 | 2016 | 2016-04-07 | 0 | regular | ANA01 | ANA | TEX | 4 | 3 | night | 39089 | 191 |
| ANA201604080 | 2016 | 2016-04-08 | 0 | regular | ANA01 | ANA | TEX | 3 | 7 | night | 35207 | 210 |
| ANA201604090 | 2016 | 2016-04-09 | 0 | regular | ANA01 | ANA | TEX | 1 | 4 | night | 38106 | 173 |
| ANA201604100 | 2016 | 2016-04-10 | 0 | regular | ANA01 | ANA | TEX | 3 | 1 | day | 35097 | 163 |
- game_idtext · unique id
- ANA201604040
- seasonnumber · links to seasons
- 2016
- game_datedate
- 2016-04-04
- game_numbernumber
- 0
- game_typetext
- regular
- venue_idtext · links to venues
- ANA01
- home_team_idtext · links to teams
- ANA
- away_team_idtext · links to teams
- CHN
- home_scorenumber
- 0
- away_scorenumber
- 9
- day_nighttext
- night
- attendancenumber
- 44020
- duration_minutesnumber
- 188
- game_idtext · unique id
- ANA201604050
- seasonnumber · links to seasons
- 2016
- game_datedate
- 2016-04-05
- game_numbernumber
- 0
- game_typetext
- regular
- venue_idtext · links to venues
- ANA01
- home_team_idtext · links to teams
- ANA
- away_team_idtext · links to teams
- CHN
- home_scorenumber
- 1
- away_scorenumber
- 6
- day_nighttext
- night
- attendancenumber
- 37042
- duration_minutesnumber
- 154
- game_idtext · unique id
- ANA201604070
- seasonnumber · links to seasons
- 2016
- game_datedate
- 2016-04-07
- game_numbernumber
- 0
- game_typetext
- regular
- venue_idtext · links to venues
- ANA01
- home_team_idtext · links to teams
- ANA
- away_team_idtext · links to teams
- TEX
- home_scorenumber
- 4
- away_scorenumber
- 3
- day_nighttext
- night
- attendancenumber
- 39089
- duration_minutesnumber
- 191
- game_idtext · unique id
- ANA201604080
- seasonnumber · links to seasons
- 2016
- game_datedate
- 2016-04-08
- game_numbernumber
- 0
- game_typetext
- regular
- venue_idtext · links to venues
- ANA01
- home_team_idtext · links to teams
- ANA
- away_team_idtext · links to teams
- TEX
- home_scorenumber
- 3
- away_scorenumber
- 7
- day_nighttext
- night
- attendancenumber
- 35207
- duration_minutesnumber
- 210
- game_idtext · unique id
- ANA201604090
- seasonnumber · links to seasons
- 2016
- game_datedate
- 2016-04-09
- game_numbernumber
- 0
- game_typetext
- regular
- venue_idtext · links to venues
- ANA01
- home_team_idtext · links to teams
- ANA
- away_team_idtext · links to teams
- TEX
- home_scorenumber
- 1
- away_scorenumber
- 4
- day_nighttext
- night
- attendancenumber
- 38106
- duration_minutesnumber
- 173
- game_idtext · unique id
- ANA201604100
- seasonnumber · links to seasons
- 2016
- game_datedate
- 2016-04-10
- game_numbernumber
- 0
- game_typetext
- regular
- venue_idtext · links to venues
- ANA01
- home_team_idtext · links to teams
- ANA
- away_team_idtext · links to teams
- TEX
- home_scorenumber
- 3
- away_scorenumber
- 1
- day_nighttext
- day
- attendancenumber
- 35097
- duration_minutesnumber
- 163
first 6 of 23,168 rows · your queries use all of them
player_game_stats17 columns · 73,029 rows
| game_idtext · links to games | player_idtext · links to players | team_idtext · links to teams | batting_ordernumber | startednumber | plate_appearancesnumber | at_batsnumber | runsnumber | hitsnumber | doublesnumber | triplesnumber | home_runsnumber | rbinumber | walksnumber | strikeoutsnumber | stolen_basesnumber | hit_by_pitchnumber |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ANA202504040 | adelj001 | ANA | 8 | 1 | 5 | 5 | 0 | 2 | 1 | 0 | 0 | 3 | 0 | 2 | 0 | 0 |
| ANA202504040 | andet001 | ANA | 4 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| ANA202504040 | ariag002 | CLE | 8 | 1 | 4 | 2 | 1 | 1 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
| ANA202504040 | clase001 | CLE | NULL | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| ANA202504040 | danac001 | ANA | NULL | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| ANA202504040 | darnt001 | ANA | 9 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- game_idtext · links to games
- ANA202504040
- player_idtext · links to players
- adelj001
- team_idtext · links to teams
- ANA
- batting_ordernumber
- 8
- startednumber
- 1
- plate_appearancesnumber
- 5
- at_batsnumber
- 5
- runsnumber
- 0
- hitsnumber
- 2
- doublesnumber
- 1
- triplesnumber
- 0
- home_runsnumber
- 0
- rbinumber
- 3
- walksnumber
- 0
- strikeoutsnumber
- 2
- stolen_basesnumber
- 0
- hit_by_pitchnumber
- 0
- game_idtext · links to games
- ANA202504040
- player_idtext · links to players
- andet001
- team_idtext · links to teams
- ANA
- batting_ordernumber
- 4
- startednumber
- 0
- plate_appearancesnumber
- 1
- at_batsnumber
- 1
- runsnumber
- 0
- hitsnumber
- 0
- doublesnumber
- 0
- triplesnumber
- 0
- home_runsnumber
- 0
- rbinumber
- 0
- walksnumber
- 0
- strikeoutsnumber
- 0
- stolen_basesnumber
- 0
- hit_by_pitchnumber
- 0
- game_idtext · links to games
- ANA202504040
- player_idtext · links to players
- ariag002
- team_idtext · links to teams
- CLE
- batting_ordernumber
- 8
- startednumber
- 1
- plate_appearancesnumber
- 4
- at_batsnumber
- 2
- runsnumber
- 1
- hitsnumber
- 1
- doublesnumber
- 0
- triplesnumber
- 0
- home_runsnumber
- 0
- rbinumber
- 0
- walksnumber
- 2
- strikeoutsnumber
- 0
- stolen_basesnumber
- 0
- hit_by_pitchnumber
- 0
- game_idtext · links to games
- ANA202504040
- player_idtext · links to players
- clase001
- team_idtext · links to teams
- CLE
- batting_ordernumber
- NULL
- startednumber
- 0
- plate_appearancesnumber
- 0
- at_batsnumber
- 0
- runsnumber
- 0
- hitsnumber
- 0
- doublesnumber
- 0
- triplesnumber
- 0
- home_runsnumber
- 0
- rbinumber
- 0
- walksnumber
- 0
- strikeoutsnumber
- 0
- stolen_basesnumber
- 0
- hit_by_pitchnumber
- 0
- game_idtext · links to games
- ANA202504040
- player_idtext · links to players
- danac001
- team_idtext · links to teams
- ANA
- batting_ordernumber
- NULL
- startednumber
- 0
- plate_appearancesnumber
- 0
- at_batsnumber
- 0
- runsnumber
- 0
- hitsnumber
- 0
- doublesnumber
- 0
- triplesnumber
- 0
- home_runsnumber
- 0
- rbinumber
- 0
- walksnumber
- 0
- strikeoutsnumber
- 0
- stolen_basesnumber
- 0
- hit_by_pitchnumber
- 0
- game_idtext · links to games
- ANA202504040
- player_idtext · links to players
- darnt001
- team_idtext · links to teams
- ANA
- batting_ordernumber
- 9
- startednumber
- 0
- plate_appearancesnumber
- 1
- at_batsnumber
- 1
- runsnumber
- 0
- hitsnumber
- 0
- doublesnumber
- 0
- triplesnumber
- 0
- home_runsnumber
- 0
- rbinumber
- 0
- walksnumber
- 0
- strikeoutsnumber
- 0
- stolen_basesnumber
- 0
- hit_by_pitchnumber
- 0
first 6 of 73,029 rows · your queries use all of them
worked example
Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.
Add up home runs per player. Run this first. Each row is one player’s total home runs for the 2025 regular season—you rank totals like this, not single-game lines.
step-1.sqlSELECT s.player_id, SUM(s.home_runs) AS home_runs FROM player_game_stats s JOIN games g ON g.game_id = s.game_id WHERE g.game_type = 'regular' GROUP BY s.player_id ORDER BY home_runs DESC LIMIT 15;
Rank teams by win total. Run this. RANK() gives the same number to teams tied on wins and skips the next slot after a tie (1, 2, 2, 4).the pattern
example.sqlSELECT team_id, wins, RANK() OVER (ORDER BY wins DESC) AS wins_rank FROM standings WHERE season = 2024 AND as_of_date = ( SELECT last_regular_date FROM seasons WHERE season = 2024 );
common mistake
Ranking batting lines instead of player totals ranks single games, not seasons.