offdataai
Media, Gaming & Sports · data model template

Sports Analytics data model

Kimball warehouse for sports analytics: transaction-grain play-by-play events with spatial coordinates, transaction-grain player game stat lines, and a daily team-standings periodic snapshot over conformed player/team/game/venue/season/position dimensions. Player and team histories are tracked with SCD2.

Sports performance analytics covering play-by-play game events, player per-game box scores, and daily team standings snapshots over conformed player, team, game, venue, season, and position dimensions — a Kimball star schema with SCD2 player and team history. It is a Kimball dimensional model: fact tables at a declared grain surrounded by conformed dimensions, ready for BI tools and a semantic layer.

KimballMedia, Gaming & SportsGDPR
11
tables
119
columns
16
relationships
3
PII columns

Opening the template creates a project with the ERD, platform-native DDL, a dbt project and documentation already generated (recommended platform: Databricks). Edit it in plain English or on the canvas, then ship it to any supported warehouse.

Subject areas

play_by_playplayer_performancestandingsconformed_dimensions

Design decisions

  • Play-by-play as a transaction-grain fact

    Each on-field event (shot, pass, foul) is an atomic action with spatial and clock context; a transaction grain enables advanced tracking, possession, and win-probability models.

  • Separate player-game-stats fact from play-by-play

    Box-score totals are at player/game grain while events are at the play grain; keeping them separate avoids mixed-grain aggregation and serves fantasy/reporting use cases directly.

  • Daily standings snapshot

    Win percentage, rank, and games-back are semi-additive standings metrics that evolve daily; a periodic snapshot supports trend and playoff-probability analysis without replaying every game.

  • SCD2 on player and team

    Player team, jersey, and status change with trades and injuries, and team coach/division can change; SCD2 preserves the attributes in effect at each game.

Tables in the Sports Analytics model

Every table with its grain, columns, types and keys. PK marks a primary key, BK a business key and PII a column classified as personal data, which gets a masking strategy by default.

Fact tables (3)

fct_game_event

Grain: one row per play-by-play event (transaction)

Transaction-grain play-by-play — one row per on-field event.

ColumnTypeKeys
game_event_keybigintPK
date_keybigint
game_keybigint
player_keybigint
team_keybigint
position_keybigint
event_type_keybigint
season_keybigint
event_idvarchar
periodsmallint
game_clock_secondsinteger
event_sequenceinteger
points_scoredsmallint
x_coordinatedecimal
y_coordinatedecimal
is_successfulboolean
is_scoring_playboolean

fct_player_game_stats

Grain: one row per player per game (transaction)

Transaction-grain box-score line — one row per player per game.

ColumnTypeKeys
player_game_stats_keybigintPK
date_keybigint
game_keybigint
player_keybigint
team_keybigint
position_keybigint
season_keybigint
minutes_playeddecimal
pointssmallint
assistssmallint
reboundssmallint
stealssmallint
blockssmallint
turnoverssmallint
foulssmallint
plus_minussmallint
shots_attemptedsmallint
shots_madesmallint
did_startboolean
performance_ratingdecimal

fct_team_standings_snapshot

Grain: one row per team per season per day (periodic snapshot)

Daily standings snapshot — ranks and win pct are semi-additive.

ColumnTypeKeys
date_keybigint
team_keybigint
season_keybigint
games_playedsmallint
winssmallint
lossessmallint
tiessmallint
win_percentagedecimal
points_forinteger
points_againstinteger
point_differentialinteger
conference_ranksmallint
division_ranksmallint
games_backdecimal
streakvarchar

Dimension tables (6)

dim_date

Grain: one row per calendar day

ColumnTypeKeys
date_keybigintPK
full_datedateBK
day_of_weekvarchar
month_numbersmallint
quartersmallint
yearsmallint
is_weekendboolean
is_holidayboolean

dim_player

Grain: one row per player per SCD2 version

SCD type 2

ColumnTypeKeys
player_keybigintPK
player_idvarcharBK
first_namevarcharPII
last_namevarcharPII
date_of_birthdatePII
nationalityvarchar
height_cmsmallint
weight_kgsmallint
handednessvarchar
jersey_numbersmallint
current_team_idvarchar
draft_yearsmallint
rookie_flagboolean
statusvarchar

dim_team

Grain: one row per team per SCD2 version

SCD type 2

ColumnTypeKeys
team_keybigintPK
team_idvarcharBK
team_namevarchar
team_abbreviationvarchar
cityvarchar
conferencevarchar
divisionvarchar
head_coachvarchar
founded_yearsmallint
home_venue_idvarchar

dim_game

Grain: one row per scheduled game

ColumnTypeKeys
game_keybigintPK
game_idvarcharBK
home_team_idvarchar
away_team_idvarchar
game_typevarchar
week_numbersmallint
attendanceinteger
broadcast_networkvarchar
is_overtimeboolean
game_statusvarchar

dim_venue

Grain: one row per venue

ColumnTypeKeys
venue_keybigintPK
venue_idvarcharBK
venue_namevarchar
cityvarchar
statevarchar
countryvarchar
capacityinteger
surface_typevarchar
is_indoorboolean
elevation_metersinteger

dim_season

Grain: one row per season

ColumnTypeKeys
season_keybigintPK
season_idvarcharBK
season_yearvarchar
leaguevarchar
season_typevarchar
start_datedate
end_datedate

Lookup tables (2)

dim_position

Grain: one row per playing position

ColumnTypeKeys
position_keybigintPK
position_codevarcharBK
position_namevarchar
position_groupvarchar

dim_event_type

Grain: one row per play event type

ColumnTypeKeys
event_type_keybigintPK
event_type_codevarcharBK
event_type_namevarchar
event_categoryvarchar

Relationships

Each relationship is a foreign key on the first table referencing the second.

  • fct_game_event.date_key → dim_date (many-to-one)
  • fct_game_event.game_key → dim_game (many-to-one)
  • fct_game_event.player_key → dim_player (many-to-one)
  • fct_game_event.team_key → dim_team (many-to-one)
  • fct_game_event.position_key → dim_position (many-to-one)
  • fct_game_event.event_type_key → dim_event_type (many-to-one)
  • fct_game_event.season_key → dim_season (many-to-one)
  • fct_player_game_stats.date_key → dim_date (many-to-one)
  • fct_player_game_stats.game_key → dim_game (many-to-one)
  • fct_player_game_stats.player_key → dim_player (many-to-one)
  • fct_player_game_stats.team_key → dim_team (many-to-one)
  • fct_player_game_stats.position_key → dim_position (many-to-one)
  • fct_player_game_stats.season_key → dim_season (many-to-one)
  • fct_team_standings_snapshot.date_key → dim_date (many-to-one)
  • fct_team_standings_snapshot.team_key → dim_team (many-to-one)
  • fct_team_standings_snapshot.season_key → dim_season (many-to-one)

Related templates

All templates →
Start for $1

From requirements to AI-ready context, in one platform.

Describe your business in a conversation, start from a template or connect your own database. Your first model is ready in minutes.

Get startedBook a demo

Plans from $1/month · cancel any time