Skip to content

Grain ladder

The statistic backbone provides a batting relation and a pitching relation at every grain a sabermetric researcher expects. Figures at a coarser grain are rolled up from the finer grain, and every rate is recomputed from the summed numerator and denominator — never averaged from finer-grain rates.

The grain ladder The game-grain relation rolls up into per-stint season lines, a combined season line, and a team-season line; the combined season line rolls up into the career line. Game batting_game / pitching_game one line per (game, player, team); counting stats only Season, per stint batting_season / pitching_season is_combined = false one line per (player, season, team) Season, combined is_combined = true, team = NULL one line per (player, season) a traded season, counted once Team season batting_team / pitching_team one line per (team, season) Career batting_career / pitching_career one line per player summed from the combined season rows

Rules the ladder enforces

  • Roll-ups flow one direction. A season line is aggregated from the game-grain relation; a career line is aggregated from the season relation's combined rows, so a player traded mid-season is counted once. A relation is never built from a sibling relation at the same grain.
  • Rates are recomputed, not averaged. A career batting average is total career H / total career AB, not the mean of the season averages. A season K% is total SO / total PA. Averaging already-computed rates would over-weight low-denominator lines (an 18-PA September call-up would count as much as a 700-PA regular).
  • A rate is null when its denominator is zero — never 0, never an error.
  • Counting stats at the game grain only. batting_game / pitching_game carry PA, AB, H, SO, BB, … but no AVG / OBP / ERA: a rate over one game's denominator is noise. Rates appear at the season, team, and career grains where the denominator is meaningful.
  • Team is part of the key at the game grain. A player who appears for both clubs in one game_id (a suspended game resumed after a trade) gets two rows, not a collision.
  • Two-way players appear in both relations at every grain.

A traded season, worked

A player who plays for two teams in 2024 has, in batting_season:

team_id is_combined meaning
TEAM A false the stint line for team A
TEAM B false the stint line for team B
NULL true the full-season line — its counting stats equal the sum of the two stint lines, and its rates are recomputed from those sums

WHERE is_combined always yields exactly one full-season line per player, which matches Baseball-Reference's 2TM / 3TM row. A one-team player's combined line equals their single stint.

See the data dictionary for the column list at each grain and the formulas page for each rate's definition.