Kathuko › SQL › Part 5: Analytic functions

5.8 19c+

Practice: three window-function problems

Three questions. Write your answer, compare it with the expected rows, then open the answer. Pads on.

1. Each team's most expensive over

For each team in 2026, the single over in which they scored the most runs while batting. If an over ties, take the earlier match, then the earlier over.

Expected result · 6 rows
TEAM_CODEMATCH_IDOVER_NORUNS
AKL20121
CHN23919
DBN271020
KHI28523
LDS32622
TPA19718
Try itShow the answer
with overs as (
  select t.team_code, b.match_id, b.over_no, sum(b.total_runs) as runs
  from   cr_balls_v b
  join   cr_teams t on t.team_id = b.batting_team_id
  where  b.season = 2026
  group  by t.team_code, b.match_id, b.over_no
)
select team_code, match_id, over_no, runs
from   (select o.*,
               row_number() over (partition by team_code order by runs desc, match_id, over_no) as rn
        from   overs o)
where  rn = 1
order  by team_code;
with overs as (
  select t.team_code, b.match_id, b.over_no, sum(b.total_runs) as runs
  from   cr_balls_v b
  join   cr_teams t on t.team_id = b.batting_team_id
  where  b.season = 2026
  group  by t.team_code, b.match_id, b.over_no
)
select team_code,
       min(match_id) keep (dense_rank first order by runs desc, match_id, over_no) as match_id,
       min(over_no)  keep (dense_rank first order by runs desc, match_id, over_no) as over_no,
       max(runs)                                                                  as runs
from   overs
group  by team_code
order  by team_code;

Top-1 per group (page 5.7), or KEEP when you only need one row and a few columns.

2. The over that changed the chase

In Leeds' chase in the 2026 final (match 32, innings 2), which over scored the most runs more than the over before it?

Expected result · 1 row
OVER_NORUNSJUMP
62212
Try itShow the answer
with overs as (
  select over_no, sum(total_runs) as runs
  from   cr_balls_v
  where  match_id = 32 and innings_no = 2
  group  by over_no
),
jumps as (
  select over_no, runs, runs - lag(runs) over (order by over_no) as jump
  from   overs
)
select over_no, runs, jump
from   jumps
where  jump = (select max(jump) from jumps);

26ai only

with overs as (
  select over_no, sum(total_runs) as runs
  from   cr_balls_v
  where  match_id = 32 and innings_no = 2
  group  by over_no
),
jumps as (
  select over_no, runs, runs - lag(runs) over (order by over_no) as jump
  from   overs
)
select over_no, runs, jump
from   jumps
qualify rank() over (order by jump desc nulls last) = 1;

Window functions can't be nested, so the jump is computed in its own step and ranked in the next.

The last powerplay over went for 22, twelve more than the over before. The first over has no previous over, so its jump is null; MAX ignores it, and NULLS LAST keeps it out of first place in the RANK.

3. The 2026 league table

The 2026 league table (league matches only): matches played, points (2 for a win, 1 for a tie), and position. Teams level on points share a position.

Expected result · 6 rows
TEAM_NAMEPLAYEDPOINTSPOS
Chennai Comets581
Leeds Larks581
Durban Dhows563
Auckland Albatross544
Karachi Kites525
Tampa Tides525
Try itShow the answer
with results as (
  select home_team_id as team_id,
         case when winner_id = home_team_id then 2 when winner_id is null then 1 else 0 end as pts
  from   cr_matches where season = 2026 and stage = 'LEAGUE'
  union all
  select away_team_id,
         case when winner_id = away_team_id then 2 when winner_id is null then 1 else 0 end
  from   cr_matches where season = 2026 and stage = 'LEAGUE'
)
select t.team_name,
       count(*)                                 as played,
       sum(r.pts)                               as points,
       rank() over (order by sum(r.pts) desc)   as pos
from   results r
join   cr_teams t on t.team_id = r.team_id
group  by t.team_name
order  by points desc, t.team_name;
with results as (
  select home_team_id as team_id,
         case when winner_id = home_team_id then 2 when winner_id is null then 1 else 0 end as pts
  from   cr_matches where season = 2026 and stage = 'LEAGUE'
  union all
  select away_team_id,
         case when winner_id = away_team_id then 2 when winner_id is null then 1 else 0 end
  from   cr_matches where season = 2026 and stage = 'LEAGUE'
),
standings as (
  select t.team_name, count(*) as played, sum(r.pts) as points
  from   results r join cr_teams t on t.team_id = r.team_id
  group  by t.team_name
)
select x.team_name, x.played, x.points,
       (select count(*) + 1 from standings y where y.points > x.points) as pos
from   standings x
order  by x.points desc, x.team_name;

rank() over (order by sum(r.pts) desc) is a window function over an aggregate: GROUP BY runs first, then the ranking. Chennai and Leeds finish level on 8 (real leagues would split them on net run rate; ours shrugs and says joint first).

Part 5 quiz

5 questions on all of Part 5. Get 4 right to pass. Retake it as often as you like.