Back to WCA Statistics

Sum of Ranks — sum of world ranks across all 17 events

Ranking

For each person, every one of the 17 official events has a world rank (events without any result get a penalty rank of "participants + 1"). The sum across all 17 is Sum of Ranks. Lower = more well-rounded — small number means broad + strong.

Default view = all 17 events × single. type=average flips to averages, country swaps in country_rank sums, and events lets you pick a subset (e.g. 333,222,444). Subset mode uses a CTE to count participants per event inline; the "participants + 1" penalty for missing events is computed within the chosen scope.

By the numbers

17
Event slots
One per ACTIVE_EVENTS slot, fixed order
~300 k
Rows
One row per (person, is_avg)
participants + 1
Missing-event penalty
One worse than the last-ranked competitor of that event
wr / cr
Two rank arrays
ranks_world + ranks_country — 17 INTEGER[] each

Data source

CI accumulates per-event PB via accByEvent[event] → Acc { best, avg }. For each event, assignRanks(sortedList) assigns both world_rank + country_rank in one pass. Per person, the 17 ranks land in two INTEGER[] columns; missing events absorb a participants + 1 penalty in the precomputed total. Podium filtering uses best_final_pos (MIN(pos>0) across every event's final-round results): no-podium = =0 OR >3, fourth-place king = =4. Stored in wca_person_ranks(wca_id, is_avg, country_id, events_done, total_world_rank, total_country_rank, best_final_pos, ranks_world[], ranks_country[]).

Subset mode — CTE counts participants per selected event; missing slots fall back to ep.pX + 1
sql
WITH ep AS (
  SELECT SUM(CASE WHEN ranks_world[1] > 0 THEN 1 ELSE 0 END) AS p0,
         SUM(CASE WHEN ranks_world[2] > 0 THEN 1 ELSE 0 END) AS p1
         /* ... more selected events ... */
  FROM wca_person_ranks WHERE is_avg = ?
)
SELECT pr.wca_id, p.name, pr.ranks_world,
       (CASE WHEN pr.ranks_world[1] > 0 THEN pr.ranks_world[1] ELSE ep.p0 + 1 END
      + CASE WHEN pr.ranks_world[2] > 0 THEN pr.ranks_world[2] ELSE ep.p1 + 1 END
       /* ... */) AS subset_total
FROM wca_person_ranks pr CROSS JOIN ep
JOIN wca_persons p ON p.wca_id = pr.wca_id
WHERE pr.is_avg = ?
ORDER BY subset_total ASC;

Algorithm / pipeline

1
Rank each event once
For each ACTIVE_EVENTS[i], pull Acc from accByEvent, sort by PB, run assignRanks() to assign world + country rank with tie handling. eventParticipantsSingle[i] / eventParticipantsAvg[i] remember each event's competitor count.
2
Build 17-slot arrays + missing penalty
Per (pid, is_avg): build 17-slot ranksW[i] = eventRanks[i].get(pid)?.wr ?? 0 (likewise ranksC). The total adds either wr or the participants + 1 penalty for missing slots. 333mbf has no average — that slot stays 0 and is skipped in the average-view total.
3
Record best_final_pos / events_done
In the main loop, every result with round_type_id IN ('c', 'f') and pos > 0 updates that person's best_final_pos = MIN(pos) across events. 0 = never produced a valid final-round result. events_done counts slots with wr > 0. /v1/wca/sum-of-ranks?hidePodium=1best_final_pos = 0 OR > 3; ?bestMisser=4best_final_pos = 4 (fourth-place king).
4
All 17 events → use precomputed total
No events param (or all 17): ORDER BY total_world_rank (no country) or total_country_rank (with country), riding pr_total / pr_country_total. Sub-millisecond.
5
Subset → CTE + array indexing on the fly
A real subset was passed: CTE ep counts participants per selected event; the main query builds subset_total with CASE WHEN ranks_X[i+1] > 0 THEN ... ELSE ep.pX + 1 END and ORDER BY subset_total ASC. The CTE is not affected by hidePodium — participant count is intrinsic to the event.

Key formulae

Formula
totalRank(p) = Σₑ (rank(p, e) if rank > 0 else participants(e) + 1)
e ranges over all 17 events (or chosen subset). rank(p, e) = 0 indicates no result in that event, fallback to "participants + 1" (one worse than the bottom-ranked competitor).

Caveats & edges

Related stats & links