MMOLDB

This page lists the 3 schemata of MMOLDB, each table within them, and each column of each table.

The formatting is hopefully serviceable, but not ideal. We are eagerly accepting any help to improve the looks and legibility over at the MMOLDB github and discord channel.

taxa

Contains categorical information. You can think of each taxa table as an enum, and each row as a variant of that enum. The difference between taxa and an actual enum is that taxa tables have extra columns with properties about the variants.

The correct way to use any column that references a taxa is to join on said taxa table and use the taxa's name in your where and group by clauses. However, I recognize that I won't be able to stop people from using IDs instead, so those are guaranteed to be stable.

taxa.event_type

The outcome of the pitch (or lack of pitch, in the case of a balk). The types are very granular to facilitate grouping them in as many ways as possible. Some common ways to group events are provided by the many boolean is_* columns.

Name Type Description
id bigint

An arbitrary ID for an event type. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using event type ids in your queries or results.

name text

The code-friendly name for this event type. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this event type.

ends_plate_appearance boolean

Does an event of this type end the current plate appearance?

is_in_play boolean

Does an event of this type result in a ball in play?

is_hit boolean

Does an event of this type count as a hit, for the purposes of batter statistics?

is_error boolean

Does an event of this type count as an error, for the purposes of both batter and pitcher statistics?

is_ball boolean

Does an event of this type represent a pitch outside the strike zone on which the batter did not swing?

is_strike boolean

Does an event of this type represent either a pitch inside the strike zone or a pitch on which the batter swung?

is_strikeout boolean

Does an event of this type count as a strikeout, for the purposes of pitcher statistics?

is_basic_strike boolean

Does an event of this type count as either a strikeout or a non-PA-ending strike?

is_foul boolean

Does an event of this type count as a foul ball or foul tip?

is_foul_tip boolean

Does an event of this type count as a foul tip?

batter_swung boolean

Does an event of this type represent a pitch on which the batter swung?

taxa.fielder_location

A location on the field, identified by its associated fielder position.

Name Type Description
id bigint

The standard baseball fielder number. 1 = pitcher, 2 = catcher, etc.

name text

The code-friendly name for this fielder location. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this fielder location.

abbreviation text

The standard one- or two-letter abbreviation for this fielder location.

area text

'Infield' or 'Outfield'

taxa.fair_ball_type

The characterization of a batted ball's trajectory.

Name Type Description
id bigint

An arbitrary ID for a fair ball type. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using fair ball type ids in your queries or results.

name text

The code-friendly name for this fair ball type. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this fair ball type.

taxa.slot

A possibly-approximate player slot in the roster.

MMOLB has been inconsistent in the past with how it identifies pitchers who field a ball. At different times (and in different events) they have been identified just as the pitcher ("P"), as the type of pitcher (e.g. "SP"), and with their full roster slot identification (e.g. "SP3"). We do the best we can to provide the most specific identification available.

Note that because of this MMOLB inconsistency, a position player who is currently pitching may be identified as "Pitcher" or as their assigned roster slot.

Eventually we plan to reference other sources to accurately determine the player's roster slot, at which time the approximate values will be removed from this taxa.

Approximate slots will also be used in case there is a pitcher with a higher slot than expected, e.g. "SP6" or "RP4". There are no instances of this as of this writing (at the end of Season 2).

Name Type Description
id bigint

The slot's ordinal position on the MMOLB team page, for concrete slots. For approximate slots (see the table description) this is an arbitrary number.

name text

The code-friendly name for this slot. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this slot.

abbreviation text

The standard abbreviation for this slot, as seen on the MMOLB team page.

role text

'Pitcher' or 'Batter'. NOTE: Players in a batting slot who are currently pitching may have either value. See the table description for details.

pitcher_type text or null

For pitching slots, 'Starter', 'Reliever', 'Closer', or 'Unknown'. 'Unknown' indicates this is a pitcher, but we don't know which type.

null for non-pitching slots.

slot_number integer or null

The slot number, if any (1 for SP1, 2 for SP2, etc.). You typically won't need to use this column, since it's already baked into the slot's name and abbreviation. It's provided in case it's ever convenient to manipulate a slot number numerically.

null for non-numbered slots (anything besides Starter and Reliever).

location bigint or null

The fielder location where this slot typically plays, if applicable. This is a foreign key into taxa.fielder_location.

WARNING: a player in a batting slot who is currently pitching may be recorded as occupying their batting slot or the Pitcher approximate slot, meaning their location may be recorded as Pitcher or as their typical fielder location. See the table description for details.

null for the Designated Hitter.

taxa.base

A base. Like from baseball.

Name Type Description
id bigint

The base number. Note that Home is base number 0. There is (currently) no base number 4.

This numbering was chosen to accommodate potential additional bases.

name text

The code-friendly name for this base. Guaranteed to contain alphanumeric characters only and start with a letter.

This is (currently) also the human-friendly name for this base.

bases_achieved integer

The number of bases the player has to advance to end up on this base. Equal to the base id for every base other than Home.

This column will be deleted if additional bases are ever added to MMOLB. A new column will be added (not necessarily to this schema) to record the total number of bases.

taxa.base_description_format

MMOLB occasionally describes bases in different formats. The same base may be described as "first", "first base", or "1st". This records which format was used for a particular description.

This taxa only exists for the purpose of exactly recreating game event messages from the database (aka "round-tripping"). If you find a genuine use for it in MMOLB analysis please let us know!

Name Type Description
id bigint

An arbitrary ID for a base description format. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using base description format ids in your queries or results.

name text

The code-friendly name for this base description format. Guaranteed to contain alphanumeric characters only and start with a letter.

taxa.fielding_error_type

The type of a fielding error: throwing or catching.

Name Type Description
id bigint

An arbitrary ID for a fielding error type. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using fielding error type ids in your queries or results.

name text

The code-friendly name for this base description format. Guaranteed to contain alphanumeric characters only and start with a letter.

This is (currently) also the human-friendly name.

taxa.pitch_type

Pitch type, as described by the pitch information at the right side of a pitch event.

Name Type Description
id bigint

An arbitrary ID for a pitch type. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using pitch type ids in your queries or results.

name text

The code-friendly name for this pitch type. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this pitch type.

abbreviation text

The standard baseball abbreviation for this pitch type.

taxa.pitcher_change_source

The source of a potential pitcher change.

InningChange means that the swap happened as part of the half-inning starting. This is how closers are usually brought in, for example. MoundVisit means there was separate mound visit event, where the manager vists the pitcher and may or may not swap them. These mound visits are announced as "manager is making a mound visit". PitchingChange: If the manager has already made a mound visit for this pitcher, on their next mound visit they must swap the pitcher. There is no option to have the pitcher remain in the game again. These mound visits are announced as "manager is making a pitching change."

Name Type Description
id bigint

An arbitrary ID for a pitcher change type. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using pitcher change type ids in your queries or results.

name text

The code-friendly name for this pitcher change type. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this pitcher change type.

taxa.leagues

The leagues of MMOLB, both greater and lesser.

These leagues are hard-coded. In future this taxa will be replaced with a data.leagues table which is populated dynamically from MMOLB.

This is currently not referenced in any other tables. We know it would be desired, but it will take significant work to get there.

Name Type Description
id bigint

An arbitrary ID number for a league.

name text

The league's name.

color text

The league's background color as shown on the MMOLB lesser league page. Greater league teams also have background colors in the API.

emoji text

The league's emoji.

league_type text

'Greater' or 'Lesser'.

parent_team_id text

The MMOLB team id for the league's parent team. For Lesser League teams, this is the Greater League team they're associated with. For Greater League teams, this is the league's Superstar team.

mmolb_league_id text

The MMOLB id for the league itself.

taxa.day_type

MMOLB has several time periods that are not included in the normal day count. This includes the postseason, election, and several different types of break. This taxa lists the various special "day" types, as well as the standard "Day".

Name Type Description
id bigint

An arbitrary ID for a day type. When this appears as a foreign key you are encouraged to join this taxa and use its name column, rather than directly using day type ids in your queries or results.

name text

The code-friendly name for this day type. Guaranteed to contain alphanumeric characters only and start with a letter.

display_name text

The human-friendly name for this day type.

taxa.attribute_category

The category of an attribute, e.g. "Batting" or "Defense". Luck and Priority are in the "Generic" category.

Name Type Description
id bigint

An arbitrary ID for an attribute category. When this appears as a foreign key you are encouraged to join this taxa and use its namecolumn, rather than directly using attribute category ids in your queries or results.

name text

The code-friendly name for this attribute category. Guaranteed to contain alphanumeric characters only and start with a letter.

This is also the human-friendly name for each attribute category.

taxa.attribute

Identifies a player attribute, e.g. "Intimidation" or "Luck".

Name Type Description
id bigint

An arbitrary ID for an attribute. When this appears as a foreign key you are encouraged to join this taxa and use its namecolumn, rather than directly using attribute ids in your queries or results.

name text

The code-friendly name for this attribute. Guaranteed to contain alphanumeric characters only and start with a letter.

This is also the human-friendly name for each attribute.

category bigint

This attribute's category. References taxa.attribute_category.

taxa.attribute_effect_type

How a particular effect applies to an attribute. Based on [this description][https://discord.com/channels/1136709081319604324/1148829574524850197/1368118313292398673] from the MMOLB discord there are Flat, Additive, and Multiplicative bonuses.

This determines how effects are combined with the attribute's base value to create the final effective attribute value. The formula is:

(Base + sum(Flat)) * sum(Additive) * product(Multiplicative)

Base is the base value of that attribute (visible through the player report, for example), and Flat, Additive, and Multiplicative are the three effect types.

Name Type Description
id bigint

An arbitrary ID for an attribute effect type. When this appears as a foreign key you are encouraged to join this taxa and use its namecolumn, rather than directly using attribute effect type ids in your queries or results.

name text

The code-friendly name for this attribute effect type. Guaranteed to contain alphanumeric characters only and start with a letter.

This is also the human-friendly name for each attribute effect type.

taxa.handedness

Player handedness: Left, Right, or Switch. Players have a separate batting and pitching handedness.

Name Type Description
id bigint

An arbitrary ID for a handedness. When this appears as a foreign key you are encouraged to join this taxa and use its namecolumn, rather than directly using handedness ids in your queries or results.

name text

The code-friendly name for this handedness. Guaranteed to contain alphanumeric characters only and start with a letter.

This is also the human-friendly name for each handedness.

data

This is where you mostly want to look. It contains the actual data you'll be querying.

data.weather

MMOLB weathers.

This table is populated dynamically from API data in a non-determinstic order. This means ids are not stable. You should not store weather ids between queries, nor hard-code weather ids into queries. Always join with the weather table.

Two weathers are considered distinct if their name, emoji, or tooltip are different. There may be many entries in this table with the same name, but their emoji and/or tooltip will be different.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store weather ids between queries, nor hard-code weather ids into queries. Always join with the weather table.

name text

The weather's name, as displayed on mmolb.com.

emoji text

The weather's emoji, as displayed on mmolb.com.

tooltip text

The text that appears when you hover over a weather on mmolb.com.

data.games

All* known MMOLB games. This includes incomplete games, even though we don't process game events until the game is finished.

* Excluding a set of games from Season 0 which never finished and will never finish. Those games are excluded from MMOLDB.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Always use mmolb_game_id for that instead.

ingest bigint

The ID of the ingest that added this game. References info.ingests.

Incomplete games are deleted and re-added, so a given game's ingest may change over time.

mmolb_game_id text

The MMOLB game ID. This is the preferred way to identify a game.

weather bigint

The active weather during this game. This references data.weather. Weather ids are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.weather and use the weather name (and emoji and tooltip if you like) instead.

season integer

The MMOLB season during which this game was played.

day integer or null

The MMOLB regular or postseason day during which this game was played.

null for superstar games --- they have a superstar_day instead.

Exactly one of day and superstar_day is non-null.

superstar_day integer or null

The superstar day during which this game was played.

null for non-superstar games --- they have a day instead.

Exactly one of day and superstar_day is non-null.

away_team_emoji text

The away team's emoji.

away_team_name text

The away team's name.

away_team_mmolb_id text

The away team's MMOLB ID.

away_team_final_score integer or null

The away team's final score.

null for incomplete games.

home_team_emoji text

The home team's emoji.

home_team_name text

The home team's name.

home_team_mmolb_id text

The home team's MMOLB ID.

home_team_final_score integer or null

The home team's final score.

null for incomplete games.

is_ongoing boolean

Whether this game is currently being played. This is slightly different from "not finished" because there are some bugged games from season 0 which will never finish, but they are not "ongoing".

stadium_name text or null

The name of the stadium this game was played in, if any.

null for games from before stadiums were introduced in season 3.

from_version timestamp without time zone

Identifies which version of the game object was used to generate this game and its events in mmoldb. This is primarily used by MMOLDB itself to update games when their data changes. It matches the valid_from field of the entity in chron and in data.entities.

There is almost always a matching game in data.entities, but not quite. When a game is updated, the old raw game is deleted from data.entities before the new game is processed and added to data.games. This mostly happens with ongoing games, but it can also happen with finished games.

away_team_earned_coins integer or null

The number of coins the away team earned. This includes coins earned from Prosperity weather, from Geomagnetic Storms weather, and from any other future coin-earning sources.

null in the following situations:

  1. This is not a coin-awarding weather.
  2. This is a coin-awarding weather, but there was no message about teams earning coins. This can happen in e.g. Geomagnetic Storms weather if no storm events occurred. It is not possible in Prosperity weather, even though it was at once time possible for neither team to earn any coins. In that event there is still a message, but neither team earns any coins (MMOLDB records this as both teams earning 0 coins.)
  3. This is a coin-awarding weather that MMOLDB does not yet support. If this ever occurs, we are presumably working on it.
  4. This is a coin-awarding weather, and we do support it, and there was a message about the teams earning coins, but we don't know which is the home team and which is the away team because the teams have identical names and emoji.
home_team_earned_coins integer or null

The number of coins the home team earned. This includes coins earned from Prosperity weather, from Geomagnetic Storms weather, and from any other future coin-earning sources.

See away_team_earned_coins for an explanation of what null indicates.

away_team_photo_contest_top_scorer text or null

The name of the away team's top scorer in this game's photo contest.

null in the following situations:

  1. This is not Geomagnetic Storms weather.
  2. There were no aurorae during this game, so there was no photo contest.
  3. We can't tell which player belongs to the home team because the home and away teams have the exact same name and emoji.
away_team_photo_contest_score integer or null

The score that the away team's top scoring photo earned in this game's photo contest.

See away_team_photo_contest_top_scorer for an explanation of what null indicates.

home_team_photo_contest_top_scorer text or null

The name of the home team's top scorer in this game's photo contest.

See away_team_photo_contest_top_scorer for an explanation of what null indicates.

home_team_photo_contest_score integer or null

The score that the home team's top scoring photo earned in this game's photo contest.

See away_team_photo_contest_top_scorer for an explanation of what null indicates.

data.events

The big one. Contains a row for each pitch and certain non-pitch events (e.g. balk).

This table does not contain a row for every item in the game event log. Formulaic events, like game start and end messages, batter up messages, etc. are not included. Mound visits are also not included and are currently not available anywhere in the database. Item drops, falling stars, or other weather events are also not included. These items may be added in future.

data.event_baserunners and data.event_fielders are child tables of data.events.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular event use the combination of its mmolb_game_id (which you access by joining data.games on the game_id column) and game_event_index.

game_id bigint

The id of the game this event belongs to. References the data.games table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use mmolb_game_id, which you access by joining data.games on this column.

game_event_index integer

The index of this game event (starting at 0) in its game's event log. This is used in combination with mmolb_game_id to identify a game event.

fair_ball_event_index integer or null

Fair balls emit two consecutive messages in MMOLB. The first declares that the ball is fair and gives its type and direction, then the second gives its outcome. The second event's id is stored in game_event_index and the first event's id is stored in fair_ball_event_index.

This would be more accurately named fair_ball_game_event_index but the name is already long enough as it is.

null if this event is not a fair ball.

inning integer

The inning number, 1-indexed.

There are event messages that happen during "inning 0" (before the game announces the top of the 1st), but none of them are any of the event types that we store in this table.

top_of_inning boolean

true when it's the top of the inning, false when it's the bottom.

When it's true, the home team is defending and the away team is batting. When it's false, the away team is defending and the home team is batting.

event_type bigint

The event's type. References taxa.event_type.

taxa.event_type ids are stable, but you are encouraged to join taxa.event_type and use its name column rather than directly using event type ids in your queries or results.

hit_base bigint or null

If this event is a hit, the base the batter reached. Home plate (0th base) indicates a home run. References taxa.base.

taxa.base has meaningful id numbers, so it's fine to use them directly in your queries and results (so long as you remember that home plate is 0th base). You can of course still join taxa.base if it's convenient to do so.

null if this event is not a hit.

fair_ball_type bigint or null

If this event is a fair ball, the batted ball type. References taxa.fair_ball_type.

taxa.fair_ball_type ids are stable, but you are encouraged to join taxa.fair_ball_type and use its name column rather than directly using fair ball type ids in your queries or results.

null if this event is not a fair ball.

fair_ball_direction bigint or null

If this event is a fair ball, the fielder position that ball was heading towards. References taxa.fielder_location.

taxa.fielder_location ids are stable, but you are encouraged to join taxa.fielder_location and use its name column rather than directly using fielder location ids in your queries or results.

null if this event is not a fair ball.

fair_ball_fielder_name text or null

If this event is a fair ball, the name of the fielder that ball was heading towards.

This is inferred by cross-referencing fair_ball_direction with the team's current lineup. If the lineup changes during the game in a way we can't detect, such as an augment firing during the game, this may be incorrect.

null if this event is not a fair ball.

fielding_error_type bigint or null

If this event is a fielding error, the type of error (throwing or catching). References taxa.fielding_error_type.

taxa.fielding_error_type ids are stable, but you are encouraged to join taxa.fielding_error_type and use its name column rather than directly using fielding error type ids in your queries or results.

null if this event is not a fielding error.

pitch_type bigint or null

If this event is a pitch, the type of pitch. References taxa.pitch_type.

taxa.pitch_type ids are stable, but you are encouraged to join taxa.pitch_type and use its name column rather than directly using pitch type ids in your queries or results.

null if this event is not a pitch (e.g. a balk).

pitch_speed double precision or null

If this event is a pitch, the speed of the pitch.

This value is parsed from the display text, which is (as of this writing) truncated to one decimal place.

null if this event is not a pitch (e.g. a balk).

pitch_zone integer or null

If this event is a pitch, the region of the strike zone (or near the strike zone) that the pitch went through.

The assignment of numbers to pitch zones comes straight from MMOLB. The zones are arranged like so:

11       12
   1-2-3
   4-5-6
   7-8-9
13       14

null if this event is not a pitch (e.g. a balk).

described_as_sacrifice boolean or null

Records whether MMOLB described this event as a sacrifice.

Ordinarily this would not be stored, and sacrifices would be detected by examining the baserunners. However, early in MMOLB's history, some plays were described as sacrifices despite not scoring nor advancing any runners. See the bug report on the MMOLB official discord. This means the only way to know if an event is a purported sacrifice is to store that information separately.

Although this column exists because of the bug, it is not specific to the bugged events. This will be true for events which are correctly described as sacrifices, in addition to events which are incorrectly described as sacrifices.

This column is mainly intended to ensure game event messages can be perfectly reconstructed from the database (aka "round-tripped"), but it may be useful for analysis as well.

null if events of this type cannot be a sacrifice. As of this writing, the only event types that can be sacrifices are caught outs and grounded double plays.

is_toasty boolean or null

"toasty" is an easter egg that Danny (the creator of MMOLB) has said exists to prevent a situation would otherwise be cause crash in the sim. In season 2 and earlier it manifested as the text "Perfect catch!" at the end of an event. During the s2 postseason Danny shared his intent (in Discord) to change the message to "Amazing throw!" for ground balls. That message is also how know that "toasty" is the generic term for a perfect catch or amazing throw.

This column is mainly intended to ensure game event messages can be perfectly reconstructed from the database (aka "round-tripped"), but it may be useful for analysis as well.

null if events of this type can never be toasty. Note that toasty is a very rare occurrence, so there may be events that can be toasty that we don't yet know can be toasty.

balls_before integer

Number of balls in the count before this event.

The number of balls in the count after this event can be easily computed using the helper columns on taxa.event_type. For example, if you want walks to be represented with a count of 4-X, you can use the provided balls_after function, which takes the event and event type as arguments. In a query that might look like:

select
    data.balls_after(ev, et)
from data.events ev
left join taxa.event_type et on et.id = ev.event_type

If you want the count to be zeroed for a PA-ending event, like it is on mmolb.com, use the slightly longer case when event_type.ends_plate_appearance then 0 else data.balls_after(ev, et) end. In a query that might look like:

select
    (case when
        et.ends_plate_appearance
    then
        0
    else
        data.balls_after(ev, et)
    end)
from data.events ev
left join taxa.event_type et on et.id = ev.event_type
strikes_before integer

Number of strikes in the count before this event.

The number of strikes in the count after this event can be easily computed using the helper columns on taxa.event_type. For example, if you want outs and batted balls to add to the strike total, you can use the provided strikes_after function, which takes the event and event type as arguments. In a query that might look like:

select
    data.strikes_after(ev, et)
from data.events ev
left join taxa.event_type et on et.id = ev.event_type

If you want strikeouts (including foul tip strikeouts) to add to the count, but not batted balls, replace is_strike with is_basic_strike.

If you want the count to be zeroed for a PA-ending event, like it is on mmolb.com, use the slightly longer case when event_type.ends_plate_appearance then 0 else data.strikes_after(event, event_type) end. In a query that might look like:

select
    (case when
        et.ends_plate_appearance
    then
        0
    else
        data.strikes_after(ev, et)
    end)
from data.events ev
left join taxa.event_type et on et.id = ev.event_type
outs_before integer

The number of outs in the half-inning before this event.

outs_after integer

The number of outs in the half-inning after this event.

Computing outs_after within a query, while possible, is much more complicated than balls_after or strikes_after. It's also unambiguous, unlike balls_after or strikes_after.

errors_before integer

The number of errors in the half-inning before this event. This is primarily useful for calculating earned runs.

errors_after integer

The number of errors in the half-inning after this event. This is primarily useful for calculating earned runs.

away_team_score_before integer

The away team's score before this event.

away_team_score_after integer

The away team's score after this event.

home_team_score_before integer

The home team's score before this event.

home_team_score_after integer

The home team's score after this event.

pitcher_name text

The active pitcher's name.

The pitcher's ID is not yet available, but we're working on it.

pitcher_count integer

A number that starts at 0 at the beginning of each game and is incremented each time there is a pitcher change.

For the purposes of this column, a pitcher change is when a different pitching slot is chosen to be the active pitcher for this game. When pitchers are swapped as a result of an ejection, an augment, or when a player Retires and is replaced in the middle of a game (due to a falling star, for example) this number does not increase. Note that augments have fired during games as late as Season 2 (although after season 0 it's rare).

Each team maintains a separate pitcher_count. The pitcher_count stored in an event is the defending team's pitcher_count. Use top_of_inning to tell which team is defending.

batter_name text

The active batter's name.

The batter's ID is not yet available, but we're working on it.

batter_count integer

A number that starts at 0 at the start of each game and is incremented each time a different batter begins a PA.

Note that this does not increase when the same batter begins a PA multiple times in a row. As of Season 2 this only happens when the previous PA was interrupted by an inning-ending caught stealing. To separate multiple consecutive appearances by the same batter, use batter_subcount.

This number also does not increase when a batter is swapped mid-PA as a result of an augment, or when a player Retires and is replaced in the middle of a PA (due to a falling star, for example). Note that augments have fired during games as late as Season 2 (although after season 0 it's rare).

Each team maintains a separate batter_count. The batter_count stored in an event is the batting team's batter_count. Use top_of_inning to tell which team is batting.

batter_subcount integer

A number that is reset to 0 each time batter_count changes and is incremented each time the previously-active batter begins a new PA.

As of Season 2 this only happens when the previous PA was interrupted by an inning-ending caught stealing. As of Season 2 the only possible values for batter_subcount are 0 and 1, but future game mechanics may make higher numbers possible.

This is used in combination with batter_count to group plate appearances. If you want to group all the pitches, from before and after the caught-stealing, into a single plate appearance use group by batter_count. If you want to count the interrupted plate appearance and the subsequent plate appearances as two separate groups of events, use group by batter_count, batter_subcount. If you want to only include events from the last consecutive plate appearance (discarding the rest), the query is more complicated. Here's an example:

select
    count(1)
from data.events e
where batter_subcount = (
    select max(batter_subcount)
    from data.events e2
    where e2.game_id = e.game_id
      and e2.top_of_inning = e.top_of_inning
      and e2.batter_count = e.batter_count)
group by
    game_id,
    top_of_inning,
    batter_count,
    batter_subcount

Note that if you only want the last event in each group of consecutive plate appearances, it's sufficient to group by batter_count and then select the row with the highest game_event_index, which should be much faster.

Or, if you only want the plate-appearance-ending events, join taxa.event_type and filter on ends_plate_appearance. As of Season 2 there should only be one event with ends_plate_appearance = true for each (game_id, top_of_inning, batter_count) combination.

cheer text or null

The crowd's cheer on this event, if any.

Note: Cheers on fair balls are from the event referenced by fair_ball_event_index. Cheers on other event types are from the event referenced by game_event_index.

WARNING: This column may be turned into a foreign key reference soon, similar to weather. Treat it as unstable.

null for events where the crowd did not cheer.

data.event_baserunners

Baserunner activity for each event in data.events.

This contains a row for every baserunner that existed at any point during each event. That includes runners who stayed on the same base, runners who scored, and batters who become batter-runners but are called out before reaching a base.

The particulars:

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular baserunner on a particular event use the combination of its mmolb_game_id, game_event_index, and base_before. You have to join the data.events table to access game_event_index, and from there join the data.games tables to access mmolb_game_id.

event_id bigint

The id of the event this baserunner belongs to. References the data.events table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use the combination of mmolb_game_id and game_event_index as described in the documentation for data.events' id column.

baserunner_name text

The baserunner's name.

The baserunner's ID is not yet available, but we're working on it.

base_before bigint or null

The base the runner occupied before this event. References taxa.base.

null indicates this is the batter-runner. The batter is not considered to be at any base while they are batting.

base_after bigint

The base the runner occupied after this event, or the base they were put out at. References taxa.base.

Runners who score always have a row in this table with base_after = 0.

Most queries which reference this column should also reference is_out.

is_out boolean

Whether the runner was put out on this event. If so, base_after is the base they were put out at.

base_description_format bigint or null

The flavor used to describe which base the player reached or was put out at. References taxa.base_description_format.

MMOLB describes the same base in different ways for variety. This column stores which way was used for a particular event, mostly for use in reconstructing event text.

null for event types which never describe a base.

steal boolean

Whether this baserunner attempted to steal a base during this event. Reference is_out to tell whether the attempt was successful.

source_event_index integer or null

The index of the event that put this baserunner on base. Primarily useful for calculating earned runs.

null if this baserunner did not reach base as a result of a pitch. For example, automatic runners in extra innings don't have a source_event_index.

is_earned boolean

True if this runner scoring would count as an earned run for the pitcher referenced by source_event_index. If false, this runner's score will never count as an earned run.

data.event_fielders

Fielder activity for each event in data.events.

This contains a row for every fielder involved in the play.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular baserunner on a particular event use the combination of its mmolb_game_id, game_event_index, and play_order. You have to join the data.events table to access game_event_index, and from there join the data.games tables to access mmolb_game_id.

event_id bigint

The id of the event this fielder belongs to. References the data.events table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use the combination of mmolb_game_id and game_event_index as described in the documentation for data.events' id column.

fielder_name text

The fielder's name.

The fielder's ID is not yet available, but we're working on it.

fielder_slot bigint

A best-effort attempt at recording the fielder's slot. Due to various inconvenient behaviors of MMOLB this is not always accurate. References taxa.slot.

At various times in MMOLB's short history, and for various event types, the fielders have been identified differently. There are two main issues:

  1. Pitchers are sometimes described as "P" (for "Pitcher"), and at other times with their assigned slot on the team's roster. This means that when a position player is pitching, and fields the ball, they are sometimes (correctly) called "pitcher" and other times (incorrectly) labeled with the position they usually play.
  2. Players on superstar teams play different positions than they do on their usual teams. Superstar games sometimes describe the player with their correct position for the superstar team, and other times (incorrectly) use the position that player has on usual team.

See the documentation of taxa.slot for even more details.

We want to correct these errors within MMOLDB, but it's going to take some time to lay the groundwork that will allow us to do so. In the meantime, take this value with a handful of salt.

play_order integer

The order of this fielder within the play. This is primarily used as a sort key. It can also be used along with mmolb_game_id and game_event_index to uniquely and stably identify a row in this table. See the documentation of id for more.

data.events_extended

A view into data.events pre-joined with data.games with some additional fields added.

In addition to the fields below, it has all the fields of data.events and all the fields of data.games except id.

Name Type Description
batting_team_mmolb_id text

The batting team's MMOLB ID. Equal to away_team_mmolb_id during the top of the inning and home_team_mmolb_id during the bottom.

defending_team_mmolb_id text

The defending team's MMOLB ID. Equal to home_team_mmolb_id during the top of the inning and away_team_mmolb_id during the bottom.

game_end_time timestamp without time zone or null

The time that this game ended, as derived from the game outcome message in the participant teams' feeds.

The game appears in the feeds of both teams (sometimes more than once per team), and with slightly different timestamps. game_end_time takes the earliest timestamp.

null if the game doesn't appear in any team feeds. There are quite a few games where this is null and I haven't looked into why.

data.entities

A mirror of Chron's entities endpoint for selected kinds. Currently only holds kind == "game".

NOTE: Unlike Chron, a given entity kind is either in this table or data.versions, not both. kinds for which MMOLDB uses historical data are stored in data.versions, and those for which MMOLDB doesn't use historical data are stored in data.entities. Not all Chron kinds are ingested.

Name Type Description
kind text

The kind of the entity, e.g. "game", "team", "player", etc. Matches Chron's kind.

The type of this field may be changed in the future.

entity_id text

The entity's MMOLB id.

valid_from timestamp without time zone

The earliest date that Chron observed this version of the entity. This may not (and typically will not) line up perfectly with when this version was created because Chron can only poll so often.

Note entities doesn't have a valid_to column because it only stores the latest version of each entity, for which valid_to is always null.

data jsonb

The actual data of the entity. This is the data exactly as returned by the MMOLB API with no modification, so structure is subject to change whenever the API changes.

data.versions

A mirror of Chron's entities endpoint for selected kinds. Currently holds every kind that MMOLDB uses except for "game".

NOTE: Unlike Chron, a given entity kind is either in this table or data.entities, not both. kinds for which MMOLDB uses historical data are stored in data.versions, and those for which MMOLDB doesn't use historical data are stored in data.entities. Not all Chron kinds are ingested.

Name Type Description
kind text

The kind of the entity, e.g. "game", "team", "player", etc. Matches Chron's kind.

The type of this field may be changed in the future.

entity_id text

The entity's MMOLB id.

valid_from timestamp without time zone

The earliest date that Chron observed this version of the entity. This may not (and typically will not) line up perfectly with when this version was created because Chron can only poll so often.

valid_to timestamp without time zone or null

The earliest date after valid_from that Chron observed a different version of this entity -- that is, the first date where we're sure this entity was no longer valid. This may not (and typically will not) line up perfectly with when this version was actually invalidated because Chron can only poll so often.

null if this version is still valid.

data jsonb

The actual data of the entity. This is the data exactly as returned by the MMOLB API with no modification, so structure is subject to change whenever the API changes.

data.aurora_photos

A record of players snapping photos of the aurora during Geomagnetic Storms weather. Every event with aurora photos has two, one from each team, and they are stored as separate rows in this table. is_listed_first identifies which one is listed first.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular aurora photo use the combination of its mmolb_game_id, game_event_index, and is_listed_first. You have to join the data.events table to access game_event_index, and from there join the data.games tables to access mmolb_game_id.

event_id bigint

The id of the event this aurora photo belongs to. References the data.events table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use the combination of mmolb_game_id and game_event_index as described in the documentation for data.events' id column.

is_listed_first boolean

true if this photo was the first one listed in its event, false if it was the second.

There's always one photo from each team, but there's not enough information in the event itself to know which team, so MMOLDB doesn't attempt to record that.

team_emoji text

The team emoji of the player who took this picture.

player_slot bigint

The roster slot of the player who took this picture. References taxa.slot.

player_name text

The name of the player who took this picture.

data.ejections

Instances of players being ejected by ROBO-UMP.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular ejection use the combination of its mmolb_game_id and game_event_index. You have to join the data.events table to access game_event_index, and from there join the data.games tables to access mmolb_game_id.

event_id bigint

The id of the event this ejection happend on. References the data.events table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use the combination of mmolb_game_id and game_event_index as described in the documentation for data.events' id column.

team_emoji text

The team emoji of the player who was ejected.

team_name text

The team name of the player who was ejected.

ejected_player_name text

The name of the player who was ejected.

ejected_player_slot bigint

The roster slot of the player who was ejected. References taxa.slot.

violation_type text

The type of violation, e.g. "Communication" or "Sportsmanship".

reason text

The reason for the ejection.

replacement_player_name text

The name of the player is taking the place of the ejected player.

replacement_player_slot bigint or null

The roster slot of the player who is taking the place of the ejected player, if one is given. References taxa.slot.

null if the replacement is a bench player.

data.door_prizes

Door prizes earned, and not earned, during Party weather.

There's a row in this table every time the player could win a door prize, regardless whether they did win one.

Tokens won as a door prize are included directly on this table. Items won as a door prize are stored on data.door_prize_items.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store door prize ids between queries, nor hard-code door prize ids into queries.

event_id bigint

The id of the event this door prize happend on. References the data.events table.

Event IDs are not stable. You should not store event ids between queries, nor hard-code them into queries. Instead use the combination of mmolb_game_id and game_event_index as described in the documentation for data.events' id column.

door_prize_index integer

Index of this door prize within the event. There can be two door prizes in the event that the batter and pitcher are both new to the game.

player_name text

Name of the player who recieved this door prize.

tokens integer or null

The number of tokens the player won as a door prize, if any.

null if the player won items as their door prize, or if the player didn't win any door prize.

You need to also reference data.door_prize_items

data.door_prize_items

Items earned as a door prize.

This table is meant to be used in conjunction with data.door_prizes.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store door prize item ids between queries, nor hard-code door prize item ids into queries.

event_id bigint

The id of the event this door prize item was awarded on. References the data.events table.

Event IDs are not stable. You should not store event ids between queries, nor hard-code them into queries. Instead use the combination of mmolb_game_id and game_event_index as described in the documentation for data.events' id column.

door_prize_index integer

Index of this door prize within the event. There can be two door prizes in the event that the batter and pitcher are both new to the game.

item_index integer

Index of this item within the list of items the player won. There can be at least 12 (yes, twelve) items awarded as a single prize.

emoji text

The item's emoji.

name text

The item's name.

See documentation for name on data.player_equipment_versions for more about how item names work.

rare_name text or null

The item's rare name.

See documentation for rare_name on data.player_equipment_versions for more about how rare names work.

null if this item is not Rare or higher.

prefix text or null

The item's prefix. Note that unlike general items, door prize items may have at most one prefix.

See documentation for prefixes on data.player_equipment_versions for more about how prefixes work.

null if this item does not have a prefix.

suffix text or null

The item's suffix. Note that unlike general items, door prize items may have at most one suffix.

See documentation for suffixes on data.player_equipment_versions for more about how suffixes work.

null if this item does not have a suffix.

data.pitcher_changes

Pitcher changes and potential pitcher changes (so mound visits with no pitcher change are also included).

This table only includes voluntary pitcher changes. Pitcher changes due to ejection are not included.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular pitcher change use the combination of its mmolb_game_id (which you access by joining data.games on the game_id column) and game_event_index.

game_id bigint

The id of the game this pitcher change belongs to. References the data.games table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use mmolb_game_id, which you access by joining data.games on this column.

game_event_index integer

The index of this pitcher change event (starting at 0) in its game's event log. This is used in combination with mmolb_game_id identify a particular pitcher change.

previous_game_event_index integer or null

The index of the most last event to appear in data.events before this pitcher change. This is included to make it easier to access the current game state, e.g. to correlate pitcher changes with the score, the state of the bases, etc.

Note that this is not necessarily a game event where this pitcher was pitching, e.g. in the case of a pitcher swap at inning change or a mound visit that occurs before any pitches in the half-inning.

null in the unlikely event that a pitcher change occurrs before any pitches have happened in the game.

inning integer

The inning number, as in data.events.

source bigint

The source of this pitcher change ("inning change", "mound visit" or "pitcher change"). References taxa.pitcher_change_source.

top_of_inning boolean

true when it's the top of the inning, false when it's the bottom, as in data.events.

pitcher_count integer

The pitcher_count of the existing pitcher, as in data.events.

pitcher_name text

Name of the previously active pitcher. Called the "leaving pitcher" in the case of an actual pitcher change and the "remaining pitcher" in the case of a mound visit that does not result in a pitcher change.

pitcher_slot bigint

The slot of the previously active pitcher (the same pitcher identified by pitcher_name).

new_pitcher_name text or null

Name of the incoming pitcher, if there is one. References taxa.slot.

null for mound visits that do not result in a pitcher change.

The null-ness of this column is the canonical way to figure out whether a pitcher change actually occurred. pitcher_slot may be null even when a pitcher change did occur.

new_pitcher_slot bigint or null

Slot of the incoming pitcher, if there is one. References taxa.slot.

null for mound visits that do not result in a pitcher change, and for certain events that don't name the pitcher's slot.

Don't rely on this to tell whether a pitcher change actually occurred, because there are instances when a pitcher change did occur but MMOLB didn't tell us what the new slot was. Use new_pitcher_name for that instead.

data.parties

Parties that occurred during Party weather. Note that Parties are different from Door Prizes, which also happen in Party weather.

This table holds parties for individual players. Each Party game event has two parties, one for the batter and one for the pitcher.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular party use the combination of its mmolb_game_id (which you access by joining data.games on the game_id column), game_event_index, and is_pitcher.

game_id bigint

The id of the game this party belongs to. References the data.games table.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use mmolb_game_id, which you access by joining data.games on this column.

game_event_index integer

The index of this party event (starting at 0) in its game's event log. This is used in combination with mmolb_game_id and is_pitcher to identify a particular party.

is_pitcher boolean

Whether this party is for the pitcher or batter. Each party event has one party for the pitcher and one for the batter. This is used in combination with mmolb_game_id and game_event_index to identify a particular party.

top_of_inning boolean

true when it's the top of the inning, false when it's the bottom, as in data.events.

This is provided to make it easier to tell which team this party was for. If top_of_inning=is_pitcher, this party is for the a player on the home team. Otherwise this party is for a player on the away team.

player_name text

Name of the player who partied.

attribute bigint

Attribute that was boosted as a result of this party. References taxa.attribute.

value integer

Amount by which the attribute was boosted. As of mid-Season 5 this is always 50, but it may change later. Stores values as they are displayed in the game log, meaning attributes are on the 0-100 scale.

data.modifications

The possible player modifications, including Greater and Lesser boons (which are special categories of modifications).

MMOLB doesn't provide a machine-readable description of modifications' effects, and no work has yet been done on parsing them from the description. If you want that, please let us know in the Discord or Github so we know to prioritize it. Or, better yet, contribute it yourself!

This table is populated dynamically from API data in a non-determinstic order. This means ids are not stable. You should not store modification ids between queries, nor hard-code modification ids into queries. Always join with the modifications table.

Two modifications are considered distinct if their name, emoji, or description are different. There may be many entries in this table with the same name, but their emoji and/or description will be different.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store modification ids between queries, nor hard-code modification ids into queries. Always join with the modifications table.

name text

The modification's name. This is not guaranteed to be code-friendly.

emoji text

The modification's emoji.

description text

The modification's description as seen in the tooltip.

data.player_versions

Historical and current player information.

This table contains basic information about a player, like their name and birthday. It has many child tables with more advanced information like their augment and recompose history, their clubhouse reports, and their equipment. Most of these tables use valid_from and valid_until to track which version of the player data was active at any point in time.

For any of these tables, valid_from is the date (always UTC) when this version of the player was first observed, and valid_until is the date when a different version of the player was first observed, or null if this is still the active version. The range of times when the player version was valid is therefore valid_from inclusive to valid_until exclusive. The (non-null) valid_until of one version should exactly match the valid_from of the next version.

Remember that these are the dates of observations of the versions. In reality the data changed sometime between the last observation of the previous version (which is not currently exposed by chron) and the first observation of the new version. In fact, caching and network delay may mean that the change actually occurred on the "wrong" side of the valid_from/valid_until date. This should hopefully be rare.

To select only active versions, add where valid_until is null to your query. To select the version that was active at a given time t, add where valid_from <= t and (valid_until > t or valid_until is null) to your query. Remember to group that in parentheses if you're adding it to other where clauses that are combined using or.

Much of the player information is in child tables:

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a player use their mmolb_player_id.

mmolb_player_id text

The MMOLB id for this player. This is the preferred way to identify a player.

Keep in mind that recomposing players does not change their MMOLB id. If you want to separate recomposed players (and you generally should), there are two ways to do it. One is to group by name as well as id (it must be both, because there are many examples of players with the same name), and assume every name change is a recomposition. That's not strictly true, there have been players whose name was changed without a recomposition, but not many.

The other option is to use data.player_recompositions to track the generation of the player id, i.e. how many times it's been recomposed. Then each (mmolb_player_id, generation) represents a unique player. Unfortunately, there are (as yet unexplained) instances where the straightforward association between recompositions and their player version chooses the wrong player.

If you want to do it that way, you can use a query like this one:

select
	*,
	(select count(1)
	 from data.player_recompositions pr
	 where pr.mmolb_player_id=pv.mmolb_player_id
	 	and pr.time < pv.valid_from
	 ) as generation
from data.player_versions pv
limit 10 -- limit while debugging
valid_from timestamp without time zone

The earliest time this version of the player was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the player was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

first_name text

The player's first name.

Players names are usually found in full when they appear in other tables. You can assemble the player's full name with the expression first_name || ' ' || last_name.

last_name text

The player's last name.

Players names are usually found in full when they appear in other tables. You can assemble the player's full name with the expression first_name || ' ' || last_name.

batting_handedness bigint or null

Hand this player uses to bat. References taxa.handedness.

null if this player's batting handedness was not recognized. This represents an ingest error.

pitching_handedness bigint or null

Hand this player uses to pitch. References taxa.handedness.

null if this player's pitching handedness was not recognized. This represents an ingest error.

home text

The player's birthplace. This is the location of the team they were born on at the time they were born.

birthseason integer

The season during which the player was born.

birthday_type bigint or null

The type of the day during which the player was born. References taxa.day_type. See the documentation on taxa.day_type for details.

null if this player's birthday type was not recognized. This represents an ingest error.

birthday_day integer or null

The regular day during which the player was born. This should be set if and only if birthday_type is Day.

null if this player wasn't born on a regular day.

birthday_superstar_day integer or null

The superstar day during which the player was born. This should be set if and only if birthday_type is SuperstarDay.

null if this player wasn't born on a superstar day.

likes text

The thing this player likes.

dislikes text

The thing this player dislikes.

number integer

This player's number (presumably a jersey number). As far as we know this has no mechanical effect.

mmolb_team_id text or null

The MMOLB id for the team this player belongs to.

Team data can be found in data.team_versions.

null if this player is not currently on a team. Players can become teamless for many reasons, including a player Retiring after losing all their durability, being Released (full-team Release, different to Recompose) in the Hall of Unmaking, and Relegation (a season 0 mechanic which is no longer available).

slot bigint or null

The player's roster slot. References taxa.slot.

This can be used along with the player's name to more accurately connect players to game events.

null if this player's slot was not recognized. This represents an ingest error.

durability double precision

The player's durability. Displayed as a green progress bar on the player page.

This is a number that starts at 1 and is reduced by 0.05 at the end of every season, as well as when the player is damaged by a falling star. When it reaches 0, the player Retires.

greater_boon bigint or null

The player's Greater Boon, if they have one. This references data.modifications.

Modification ids (including boons) are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.modifications and use the modification name (and emoji and description if you like) instead.

null if this player does not have a Greater Boon.

lesser_boon bigint or null

The player's Lesser Boon, if they have one. This references data.modifications.

Modification ids (including boons) are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.modifications and use the modification name (and emoji and description if you like) instead.

null if this player does not have a Lesser Boon.

num_modifications integer

The number of modifications the player has.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see player modifications, use the data.player_modification_versions table.

occupied_equipment_slots ARRAY

A list of which equipment slots are occupied on this player.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see player equipment, use the data.player_equipment_versions table.

included_report_categories ARRAY

A list of which clubhouse reports are included on this player.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see player reports, use the data.player_report_versions table.

data.player_modification_versions

Records instances of modifications on players. This connects data.player_versions to data.modifications.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.player_versions. There can be a break in versions in this table without a corresponding break in versions in data.player_versions and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular modification on a particular player use the combination of its mmolb_player_id and modification_index.

mmolb_player_id text

The MMOLB id for the player this modification belongs to. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their modifications.

modification_index integer

The index of this modification in the player's modifications list. A (mmolb_player_id, modification_index) pair uniquely and stably identifies a modification on a player.

valid_from timestamp without time zone

The earliest time this version of the player modification was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the player modification was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

modification_id bigint

Which modification this is. References the data.modifications table.

Modification ids are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.modifications and use the modification name (and emoji and description if you like) instead.

data.player_equipment_versions

Records player equipment.

Though pieces of equipment are distinct objects that can theoretically be tracked as they're moved around, MMOLB doesn't provide a stable identifer for them. Because of this, we use the player and slot the item is equipped into as its identifier, and an equipment being moved from one player to another is treated as if the old item ceased to exist and the new item came into being. Same for if an existing item is modified using orbs.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.player_versions. There can be a break in versions in this table without a corresponding break in versions in data.player_versions and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular piece of equipment on a particular player use the combination of its mmolb_player_id and equipment_slot.

mmolb_player_id text

The MMOLB id for the player this equipment is equipped to. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their equipment.

equipment_slot text

The equipment slot that this piece of equipment is equipped to. Current values are:

  • Accessory
  • Body
  • Feet
  • Hands
  • Head

This may be replaced with a taxa.

A (mmolb_player_id, equipment_slot) pair uniquely and stably identifies a piece of equipment.

valid_from timestamp without time zone

The earliest time this version of the player equipment was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the player equipment was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

emoji text

The equipment's emoji.

name text

The equipment's normal name.

If the equipment has a rare_name, this name is not used. Otherwise, this name is combined with the item's prefixes and suffixes to create its displayed name.

As of the end of season 4, there is only one name for each equipment slot:

  • Accessory: Ring
  • Body: T-Shirt
  • Feet: Sneakers
  • Hands: Gloves
  • Head: Cap
special_type text or null

This field exists in the API but we've never seen a value from it.

null for every known piece of equipment.

description text or null

This field exists in the API but we've never seen a value from it.

null for every known piece of equipment.

rare_name text or null

Rare and higher magic items gain a new name that overrides the prefix-and-suffix-based default name. This is that name.

Items keep their rare name even if they are downgraded past rare with a Disintegrating Orb.

null if this item is not, and has never been, Rare or higher.

cost integer or null

Presumably, the amount the equipment cost to buy from Mother Quaelyth.

null if the cost was not an integer. This represents an ingest error.

prefixes ARRAY

A list of up to two prefixes the item has. These are prepended to name to create the item's display name, unless overridden by rare_name.

suffixes ARRAY

A list of up to two suffixes the item has. These are appended to name to create the item's display name, unless overridden by rare_name.

rarity text or null

The item's rarity. "Normal", "Magic", or "Rare".

null if the item's rarity is not a string. This represents a player ingest error.

num_effects integer

The number of effects this piece of equipment has.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see equipment effects, use the data.player_equipment_effect_versions table.

data.player_equipment_effect_versions

Records player equipment effects.

See the documentation of data.player_equipment_versions for a description of how MMOLDB handles equipment.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.player_versions, nor versions of data.player_equipment_versions. There can be a break in versions in this table without a corresponding break in versions in either of those tables and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular effect on a particular piece of equipment on a particular player use the combination of its mmolb_player_id, equipment_slot, and effect_index.

mmolb_player_id text

The MMOLB id for the player this equipment is equipped to. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their equipment.

equipment_slot text

The equipment slot that this piece of equipment is equipped to. See equipment_slot on data.player_equipment_versions for more.

effect_index integer

The index of this effect within this piece of equipment's list of effects. A (mmolb_player_id, equipment_slot, effect_index) triple uniquely and stably identifies an equipment effect.

valid_from timestamp without time zone

The earliest time this version of the player equipment effect was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the player equipment effect was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

attribute bigint

The attribute this effect modifies. References taxa.attribute.

effect_type bigint

The type of effect. References taxa.attribute_effect_type.

As of the end of season 4, the only effect type that's ever appeared is Flat.

value double precision

The value of the effect. This is stored exactly as stored in the MMOLB API (not the UI). This means that attribute values range from 0.05 to 0.20.

Note that this is a different scale from attribute augment values.

data.player_feed_versions

Records when new items appear in the player feed.

This is mainly used by MMOLDB itself. It's not likely to be useful outside of that.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.player_versions. There can be a break in versions in this table without a corresponding break in versions in data.player_versions and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular player feed use its mmolb_player_id.

mmolb_player_id text

The MMOLB id for the player this feed belongs to. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their feeds.

valid_from timestamp without time zone

The earliest time this version of the player feed was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the player feed was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

num_entries integer

The number of entries in this feed.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see the information from the feed, use the tables:

  • data.player_attribute_augments for the record of all augments to attributes each player has recieved.
  • data.player_paradigm_shifts for the record of all paradigm shifts that have affected this player.
  • data.player_recompositions for the record of all times this player has been recomposed.

data.player_attribute_augments

Records the changes to player attributes as the result of augments.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular augment use the combination of its mmolb_player_id and feed_event_index.

mmolb_player_id text

The MMOLB id for the player this that was augmented. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their augments.

feed_event_index integer

The index of this augment in the player's feed. A (mmolb_player_id, feed_event_index) pair uniquely and stably identifies an applied augment.

time timestamp without time zone

The exact time this augment was applied.

This time is given to us by the MMOLB API, rather than being the time of an API call, and so should be trustworthy.

season integer

The season during which the augment was applied.

day_type bigint or null

The type of the day during which the augment was applied. References taxa.day_type. See the documentation on taxa.day_type for details.

null if this augment's day was not recognized. This represents an ingest error.

day integer or null

The regular day during which the augment was applied. This should be set if and only if day_type is Day.

null if this augment wasn't applied on a regular day.

superstar_day integer or null

The superstar day during which the augment was applied This should be set if and only if day_type is SuperstarDay.

null if this augment wasn't applied on a superstar day.

attribute bigint

The attribute this augment modifies. References taxa.attribute.

value integer

The value by which the attribute was increased. This is stored exactly as displayed in the MMOLB UI. Common values are 5, 6, 15, 30, and 50.

data.player_paradigm_shifts

Records every instance of each player being involved in a paradigm shift.

Each paradigm shift that fires will create 9 entries in this table. MMOLDB doesn't (yet) connect the paradigm shifts to a team.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular paradigm shift use the combination of its mmolb_player_id and feed_event_index.

mmolb_player_id text

The MMOLB id for the player whose priority was changed. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their paradigm shifts.

feed_event_index integer

The index of this paradigm shift in the player's feed. A (mmolb_player_id, feed_event_index) pair uniquely and stably identifies an applied paradigm shift on a particular player.

time timestamp without time zone

The exact time this paradigm shift was applied.

This time is given to us by the MMOLB API, rather than being the time of an API call, and so should be trustworthy.

season integer

The season during which the paradigm shift was applied.

day_type bigint or null

The type of the day during which the paradigm shift was applied. References taxa.day_type. See the documentation on taxa.day_type for details.

null if this paradigm shift's day was not recognized. This represents an ingest error.

day integer or null

The regular day during which the paradigm shift was applied. This should be set if and only if day_type is Day.

null if this paradigm shift wasn't applied on a regular day.

superstar_day integer or null

The superstar day during which the paradigm shift was applied This should be set if and only if day_type is SuperstarDay.

null if this paradigm shift wasn't applied on a superstar day.

attribute bigint

The attribute this paradigm shift sorts the lineup by. References taxa.attribute.

data.player_recompositions

Records every instance of a player being recomposed.

This table is more complicated because there have been 3 distinct recompose bugs that have been handled by deleting and/or inserting inferred recompositions which aren't present in the feed. Inferred recompositions have the feed_event_index of the first feed event to happen after them, but also have an inferred_event_index.

The 3 bugs have been:

  1. Some recompositions were reverted entirely, and their events were removed from the player feed. These have been handled by suppressing the recompositions entirely, so they don't appear in this table. After more investigation the handling may or may not change to insert two inferred recompositions in quick succession, with the latter reverting the former.

  2. Some recompositions occurred without a feed event. These have been handled by adding an inferred recomposition. The time for these inferred recompositions is set to the first time we observed the recomposed player, and the season and day derived from that time.

  3. Some recompositions had their feed event and attributes reverted, but not their name change. These have been handled by suppressing the real recompositions (for the short time they appeared) and inserting an inferred recomposition to replace it (making it permanent), plus an additional recomposition when the overwrite happens. This latter recomposition doesn't change the player name, but does change their attributes. It's also marked as reverting the prior recomposition.

    Because of this bug, it is not entirely true to assume that player attributes after a recomposition are within the newly-generated-player boundaries. You can check for non-null reverts_recomposition to see if the "recomposed" player's attributes weren't freshly generated and may have been subject to augments.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular recomposition use the combination of its mmolb_player_id, inferred_event_index, and feed_event_index.

mmolb_player_id text

The MMOLB id for the player who was recomposed. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their recompositions.

inferred_event_index integer or null

For an inferred recomposition, the index of this recomposition amongst only the other inferred recompositions with the same feed_event_index.

null if this is not an inferred recompsition.

feed_event_index integer

The index of this recomposition in the player's feed, for non-inferred recompositions. For inferred recompsitions this is the index of the next event in the player's feed. See the table description for more details.

A (mmolb_player_id, inferred_event_index, feed_event_index) triple uniquely and stably identifies an applied recomposition on a particular player.

time timestamp without time zone

The exact time this recomposition was applied, for non-inferred recompositions. For inferred recompositions this time may not be exact.

This time is given to us by the MMOLB API, rather than being the time of an API call, and so should be trustworthy (except in the case of inferred recompositions).

season integer

The season during which the recomposition was applied.

day_type bigint or null

The type of the day during which the recomposition was applied. References taxa.day_type. See the documentation on taxa.day_type for details.

null if this recomposition's day was not recognized. This represents an ingest error.

day integer or null

The regular day during which the recomposition was applied. This should be set if and only if day_type is Day.

null if this recomposition wasn't applied on a regular day.

superstar_day integer or null

The superstar day during which the recomposition was applied This should be set if and only if day_type is SuperstarDay.

null if this recomposition wasn't applied on a superstar day.

player_name_before text

The player's full name before the recomposition.

player_name_after text

The player's full name after the recomposition.

reverts_recomposition timestamp without time zone or null

If this recomposition reverts another recomposition, the time of the recomposition it reverts. This means that after this recomposition, the player's attributes are set equal to what they were before the recomposition that this recomposition reverts. See the table description for more details.

null if this recomposition does not revert another recomposition.

data.player_report_versions

The contents of player clubhouse reports, also called "talk"s.

Attributes are recorded in data.player_report_attribute_versions. For many common uses of reports you can skip this table entirely and go straight to that one.

Before the Season 4 superstar break, reports displayed the player's attributes as of the creation of the report. After the Season 4 superstar break, reports display the player's current attributes (for our purposes, this means the attributes as of valid_from and until sometime before valid_until). The season and day of a report does not update live, even after the Season 4 change. For post-s4-ss reports, the season and day is not particularly useful.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.player_versions. There can be a break in versions in this table without a corresponding break in versions in data.player_versions and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular report use the combination of its mmolb_player_id and category.

mmolb_player_id text

The MMOLB id for the player who this report is about. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their reports.

category bigint

The category this report is for ("Batting", "Baserunning", etc.). References taxa.attribute_category.

valid_from timestamp without time zone

The earliest time this version of the report was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the report was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

season integer or null

The season during which the report was created.

This value only changes when a new report is generated (including the reports from Recomposing the player). Do not assume that the value of an attribute corresponds with the season that its report was generated.

null for reports that were generated before their season and day were recorded.

day_type bigint or null

The type of the day during which the report was created. References taxa.day_type. See the documentation on taxa.day_type for details.

This value only changes when a new report is generated (including the reports from Recomposing the player). Do not assume that the value of an attribute corresponds with the day_type that its report was generated.

null for reports that were generated before their season and day were recorded.

day integer or null

The regular day during which the report was created. This should be set if and only if day_type is Day.

This value only changes when a new report is generated (including the reports from Recomposing the player). Do not assume that the value of an attribute corresponds with the day that its report was generated.

null if this report wasn't created on a regular day, or if this report was generated before reports' season and day were recorded.

superstar_day integer or null

The superstar day during which the report was created. This should be set if and only if day_type is SuperstarDay.

This value only changes when a new report is generated (including the reports from Recomposing the player). Do not assume that the value of an attribute corresponds with the superstar day that its report was generated.

null if this report wasn't created on a superstar day, or if this report was generated before reports' season and day were recorded.

quote text

The quote from this player report.

included_attributes ARRAY

A list of which attributes are included in this report.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see attribute values, use the data.player_report_attribute_versions table.

data.player_report_attribute_versions

The values of attributes in player clubhouse reports.

This is a child table of data.player_report_versions, but for many common uses of attributes you don't need to reference the intermediate table.

Before the Season 4 superstar break, reports displayed the player's attributes as of the creation of the report. After the Season 4 superstar break, reports display the player's current attributes (for our purposes, this means the attributes as of valid_from and until sometime before valid_until). The season and day of a report does not update live, even after the Season 4 change. For post-s4-ss reports, the season and day is not particularly useful.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.player_versions, nor versions of data.player_report_versions. There can be a break in versions in this table without a corresponding break in versions in either of those tables and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular report attribute use the combination of its mmolb_player_id and attribute (optionally also category).

mmolb_player_id text

The MMOLB id for the player who this report attribute belongs to. Use this to join on data.player_versions (using valid_from and valid_until accordingly) to associate players with their attributes.

category bigint

The category this report is for ("Batting", "Baserunning", etc.). References taxa.attribute_category.

attribute bigint

Which attribute this is. References taxa.attribute.

valid_from timestamp without time zone

The earliest time this version of the attribute was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the report was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

stars integer

The number of stars the player has in this attribute.

data.team_versions

Historical and current team information.

This table contains basic information about a team, like their name and location. Information about which players were on the team at any given time is in data.team_player_versions. Both of these tables use valid_from and valid_until to track which version of the team data was active at any point in time.

See the data.player_versions table description for how to use valid_from and valid_until.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a team use their mmolb_team_id.

mmolb_team_id text

The MMOLB id for this team. This is the preferred way to identify a team.

valid_from timestamp without time zone

The earliest time this version of the team was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the team was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

name text

The team's name.

emoji text

The team's emoji.

color text

The team's color, in whatever format it's returned by the API.

location text

The team's location, e.g. "Baltimore".

full_location text

The team's full location, e.g. "Baltimore, MD, USA".

abbreviation text

The team's three-letter abbreviation.

As of s5d77, these are not displayed on the site anywhere. However, every team has one, automatically derived from the team name and location.

championships integer or null

The number of championships this team has won.

null if this team doesn't have a Championships field in the API. As of this writing, this applies to exactly one team: the Monongahela River Monsters Reflections, a special team created as a reflection of the Monongahela River Monsters as the conclusion of the Season 5 Kumite.

mmolb_league_id text or null

The MMOLB ID of the league this team plays in. Use taxa.leagues to get league information for now. In future there may be a data.league_versions table.

null for certain special event teams, like the Andromeda Collisions and Milky Way Two Percenters during the Season 2 special event.

ballpark_name text or null

The name of this team's ballpark, if any.

null for version from before ballparks existed.

num_players integer

The number of players the team has.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see players on the team, use the data.team_player_versions table.

data.team_player_versions

Historical and current team player information.

Records the player information that's available with the team object. This is mostly useful for the player ID.

See the data.player_versions table description for how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.team_versions, nor versions of data.player_versions. There can be a break in versions in this table without a corresponding break in versions in either of those tables and vice versa. There can also be a break in versions in this table with a corresponding break in versions in data.player_versions, but the timestamps will not be synchronized. Associating a team_player_version and a player_version is not trivial.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a team player use the combination of their mmolb_team_id and team_player_index.

mmolb_team_id text

The MMOLB id for the team this team player belongs to.

team_player_index integer

The index of this team player within the team. A (mmolb_team_id, team_player_index) pair uniquely identifies a team player.

As of s5d77 this always corresponds with position order, except for one hour from approx. 2025-04-23 00:46:24.695 to 2025-04-23 01:47:01.585 (UTC). Versions during that hour used a different format, which actually still lists players in the same order but MMOLDB doesn't handle that format's ordering correctly. We hope to fix this problem soon.

valid_from timestamp without time zone

The earliest time this version of the team player was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the team player was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

first_name text

The player's first name, as in data.player_versions.

last_name text

The player's last name, as in data.player_versions.

number integer

The player's number, as in data.player_versions.

slot bigint or null

The player's slot, as in data.player_versions.

Some old versions have a partially-known slot, like ReliefPitcher instead of ReliefPitcher1.

null if this player's slot was not present or not recognized.

mmolb_player_id text or null

The ID of the player on the team.

This references data.player_versions, but when cross-referencing team player versions with player versions be aware that the valid_from and valid_until timestamps will not be in perfect sync. When a change that's visible in both happens, like a player swap, the version in one of the tables will update probably several minutes before the other, and possibly more than that.

null if there is no player in this slot on the team, e.g. if the team is not yet fully drafted.

data.team_feed_versions

Records when new items appear in the team feed.

This is mainly used by MMOLDB itself. It's not likely to be useful outside of that.

See the documentation of data.player_versions for a description of how to use valid_from and valid_until.

Note that versions of this table do not need to coincide with versions of data.team_versions. There can be a break in versions in this table without a corresponding break in versions in data.team_versions and vice versa.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular player feed use its mmolb_team_id.

mmolb_team_id text

The MMOLB id for the team this feed belongs to. Use this to join on data.team_versions (using valid_from and valid_until accordingly) to associate teams with their feeds.

valid_from timestamp without time zone

The earliest time this version of the team feed was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of the team feed was observed, i.e. the earliest time we know this version is no longer valid. The latest time we know this version is valid is not exposed because nobody's requested it yet. If you have a use for it, contact us in the MMOLB discord or on Github.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

duplicates integer

Currently being used to debug MMOLDB itself. This field may be deleted soon.

num_entries integer

The number of entries in this feed.

This is used internally by MMOLDB itself, and is not likely to be useful to users. To see the information from the feed, see data.team_games_played.

data.team_games_played

Records of the game end notifications in team feeds. This can be used to identify which version of a player, team, etc. was active during a particular game.

There will eventually be (at least) two of these for every game, one from the feed of each of the teams. There may be zero or one temporarily depending on the timing of Chron's polling and of MMOLDB's ingest. There may also be more than two, because there has been at least one MMOLB bug that caused a game ending to be recorded more than once.

The times from this table are available on data.events_extended as game_end_time.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. To identify a particular team game played use its mmolb_team_id and feed_event_index.

mmolb_team_id text

The MMOLB id for the team this team game belongs to. Use this to join on data.team_versions (using valid_from and valid_until accordingly) to associate teams with their played games.

feed_event_index integer

The index of this team game played in the team's feed. A (mmolb_team_id, feed_event_index) pair uniquely and stably identifies a team game played.

time timestamp without time zone

The exact time this team game played was recorded.

This time is given to us by the MMOLB API, rather than being the time of an API call, and so should be trustworthy.

mmolb_game_id text

The ID of the game that this team played in.

Note there will be multiple rows with the same mmolb_game_id.

data.player_versions_extended

An expansive view that attempts to connect all the various attributes and numbers for a player, indicating what timestamp range this was the known data for the player.

This view determines all the timestamps of a player's child data (Boons, Clubhouse Reports, Equipment, Modifications, etc) and presents the data that was appropriate for the player for the time those were all the known data. Team changes (Name, Location) are excluded to avoid excessive records per player.

In particular, the timing associated with a player's Augment for the day may lack precision, as it is recorded with a timestamp that comes from MMOLB rather than using the moment the data is captured like other data points. They should be taken cautiously but listed in order to help users research data relevant to each Augment.

Name Type Description
id bigint

An arbitrary numeric ID. These IDs are not stable. You should not store these ids between queries, nor hard code them into queries. They are generated solely for the purpose of giving this view a unique column.

mmolb_player_id text

The MMOLB id for the player. This is the preferred way to identify a player. Use this to join back to any other player related tables if desired.

valid_from timestamp without time zone

The earliest time this version of this combination of player data was observed.

See the data.player_versions table description for how to use valid_from and valid_until.

valid_until timestamp without time zone or null

The earliest time a different version of this combination of player data was observed, i.e. the earliest time we know this version is no longer valid.

See the data.player_versions table description for how to use valid_from and valid_until.

null if this version is still valid.

first_name text

The player's first name.

Players names are usually found in full when they appear in other tables. You can assemble the player's full name with the expression first_name || ' ' || last_name.

last_name text

The player's last name.

Players names are usually found in full when they appear in other tables. You can assemble the player's full name with the expression first_name || ' ' || last_name.

mmolb_team_id text or null

The MMOLB id for the team this player belongs to.

Teams are planned for addition to MMOLDB, and at that time you'll be able to use this to connect a player to their team.

null if this player is not currently on a team. Players can become teamless for many reasons, including a player Retiring after losing all their durability, being Released (full-team Release, different to Recompose) in the Hall of Unmaking, and Relegation (a season 0 mechanic which is no longer available).

durability numeric

The player's durability. Displayed as a green progress bar on the player page.

This is a number that starts at 1 and is reduced by 0.05 at the end of every season, as well as when the player is damaged by a falling star. When it reaches 0, the player Retires.

position text

The standard abbreviation for this player's position, as seen on the MMOLB team page. Can be connected to other versions of the position through taxa.slot. This column can be joined on the abbreviation column of taxa.slot.

batting_handedness text or null

Hand this player uses to bat. References the name column of taxa.handedness.

null if this player's batting handedness was not recognized. This represents an ingest error.

pitching_handedness text or null

Hand this player uses to pitch. References the name column of taxa.handedness.

null if this player's pitching handedness was not recognized. This represents an ingest error.

home text

The player's birthplace. This is the location of the team they were born on at the time they were born (with some exceptions).

birthseason integer

The season during which the player was born.

birthday integer or null

The day number during which the player was born. Not all day types have a day number. As of this writing (Season 5 Offseason), only Day and SuperstarDay day types have a day number.

null if this player wasn't born on a numbered day type.

birthday_type text or null

The type of the day during which the player was born. Corresponds to the display_name column of taxa.day_type. See the documentation on taxa.day_type for details.

null if this player's birthday type was not recognized. This represents an ingest error.

greater_boon_id bigint or null

The player's Greater Boon, if they have one. This references data.modifications.

Modification ids (including boons) are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.modifications and use the modification name (and emoji and description if you like) instead.

null if this player does not have a Greater Boon.

greater_boon text or null

The name of the player's Greater Boon, if they have one.

In the event that there are multiple versions of a boon with the same name, as has happened with the Partier boon, you can use greater_boon_id to distinguish them.

null if this player does not have a Greater Boon.

lesser_boon_id bigint or null

The player's Lesser Boon, if they have one. This references data.modifications.

Modification ids (including boons) are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.modifications and use the modification name (and emoji and description if you like) instead.

null if this player does not have a Lesser Boon.

lesser_boon text or null

The name of the player's Lesser Boon, if they have one.

In the event that there are multiple versions of a boon with the same name, as has happened with the Partier boon, you can use lesser_boon_id to distinguish them.

null if this player does not have a Lesser Boon.

modification_ids ARRAY

An array of the players' modifications, if they have any. This references data.modifications. If the player has no modifications, this is the empty array.

Modification ids (including boons) are not stable. You should not store these ids between queries, nor hard-code them into queries. Always join to data.modifications and use the modification name (and emoji and description if you like) instead.

modifications ARRAY

A text array of the names of the modifications the player has. Values in this array match the name column of data.player_modification_versions.

In the event that there are multiple versions of a modification with the same name, as has happened with the Partier boon, you can use the corresponding value in modification_ids to distinguish them.

attribute_augmented text or null

If this record serves as a timestamp for when an Augment is applied to a player, it will display the text description of the Attribute that was increased.

This view currently does not reflect Augments that are not direct Attribute increases.

null if this record is not the timestam for when an Augment is applied.

augmented_amount integer or null

If this record serves as a timestamp for when an Augment is applied to a player, it will display an integer indication how much the Attribute was increased.

null if this record is not the timestam for when an Augment is applied.

accessory_equip_name text or null

If the player is wearing Equipment in the Accessory slot (Ring), then this will be the text representation of the Equipment's name, regardless if it's plain, Magic or Rare.

null if the player has no equipment in the Accessory slot (Ring).

accessory_attributes ARRAY or null

If the player's Ring has any Attribute bonuses, this will be an array of the Attributes' IDs on the taxa.attribute table.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Accessory slot (Ring). If there is a Ring equipped, but it has no attributes, this is the empty array.

accessory_effect_types ARRAY or null

If the player's Ring has any Attribute bonuses, this will be an array of the effect type on the taxa.attribute_effect_type table (Flat, Additive or Multiplicative).

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Accessory slot (Ring). If there is a Ring equipped, but it has no attributes, this is the empty array.

accessory_values ARRAY or null

If the player's Ring has any Attribute bonuses, this will be an array of the increase amount by which the attribute was boosted. Stores values as they are displayed in the game log, meaning attributes are on the 0-100 scale.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Accessory slot (Ring). If there is a Ring equipped, but it has no attributes, this is the empty array.

body_equip_name text or null

If the player is wearing Equipment in the Body slot (T-Shirt), then this will be the text representation of the Equipment's name, regardless if it's plain, Magic or Rare.

null if the player has no equipment in the Body slot (T-Shirt).

body_attributes ARRAY or null

If the player's T-Shirt has any Attribute bonuses, this will be an array of the Attributes' IDs on the taxa.attribute table.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Body slot (T-Shirt). If there is a T-Shirt equipped, but it has no attributes, this is the empty array.

body_effect_types ARRAY or null

If the player's T-Shirt has any Attribute bonuses, this will be an array of the effect type on the taxa.attribute_effect_type table (Flat, Additive or Multiplicative).

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Body slot (T-Shirt). If there is a T-Shirt equipped, but it has no attributes, this is the empty array.

body_values ARRAY or null

If the player's T-Shirt has any Attribute bonuses, this will be an array of the increase amount by which the attribute was boosted. Stores values as they are displayed in the game log, meaning attributes are on the 0-100 scale.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Body slot (T-Shirt). If there is a T-Shirt equipped, but it has no attributes, this is the empty array.

feet_equip_name text or null

If the player is wearing Equipment in the Feet slot (Sneakers), then this will be the text representation of the Equipment's name, regardless if it's plain, Magic or Rare.

null if the player has no equipment in the Feet slot (Sneakers).

feet_attributes ARRAY or null

If the player's Sneakers has any Attribute bonuses, this will be an array of the Attributes' IDs on the taxa.attribute table.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Feet slot (Sneakers). If there is a Sneakers equipped, but it has no attributes, this is the empty array.

feet_effect_types ARRAY or null

If the player's Sneakers has any Attribute bonuses, this will be an array of the effect type on the taxa.attribute_effect_type table (Flat, Additive or Multiplicative).

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Feet slot (Sneakers). If there is a Sneakers equipped, but it has no attributes, this is the empty array.

feet_values ARRAY or null

If the player's Sneakers has any Attribute bonuses, this will be an array of the increase amount by which the attribute was boosted. Stores values as they are displayed in the game log, meaning attributes are on the 0-100 scale.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Feet slot (Sneakers). If there is a Sneakers equipped, but it has no attributes, this is the empty array.

hands_equip_name text or null

If the player is wearing Equipment in the Hands slot (Gloves), then this will be the text representation of the Equipment's name, regardless if it's plain, Magic or Rare.

null if the player has no equipment in the Hands slot (Gloves).

hands_attributes ARRAY or null

If the player's Gloves has any Attribute bonuses, this will be an array of the Attributes' IDs on the taxa.attribute table.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Hands slot (Gloves). If there is a Gloves equipped, but it has no attributes, this is the empty array.

hands_effect_types ARRAY or null

If the player's Gloves has any Attribute bonuses, this will be an array of the effect type on the taxa.attribute_effect_type table (Flat, Additive or Multiplicative).

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Hands slot (Gloves). If there is a Gloves equipped, but it has no attributes, this is the empty array.

hands_values ARRAY or null

If the player's Gloves has any Attribute bonuses, this will be an array of the increase amount by which the attribute was boosted. Stores values as they are displayed in the game log, meaning attributes are on the 0-100 scale.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Hands slot (Gloves). If there is a Gloves equipped, but it has no attributes, this is the empty array.

head_equip_name text or null

If the player is wearing Equipment in the Head slot (Cap), then this will be the text representation of the Equipment's name, regardless if it's plain, Magic or Rare.

null if the player has no equipment in the Head slot (Cap).

head_attributes ARRAY or null

If the player's Cap has any Attribute bonuses, this will be an array of the Attributes' IDs on the taxa.attribute table.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Head slot (Cap). If there is a Cap equipped, but it has no attributes, this is the empty array.

head_effect_types ARRAY or null

If the player's Cap has any Attribute bonuses, this will be an array of the effect type on the taxa.attribute_effect_type table (Flat, Additive or Multiplicative).

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Head slot (Cap). If there is a Cap equipped, but it has no attributes, this is the empty array.

head_values ARRAY or null

If the player's Cap has any Attribute bonuses, this will be an array of the increase amount by which the attribute was boosted. Stores values as they are displayed in the game log, meaning attributes are on the 0-100 scale.

Note that this, along with the other Equipment arrays, are ordered by the Equipment's effect_index, keeping the order consistent across the various arrays.

null if the player has no equipment in the Head slot (Cap). If there is a Cap equipped, but it has no attributes, this is the empty array.

luck_stars integer or null

If reported, the number of stars the player has in Luck.

null if this player version has no reported Luck.

aiming_stars integer or null

If reported, the number of stars the player has in Aiming.

null if this player version has no reported Aiming.

contact_stars integer or null

If reported, the number of stars the player has in Contact.

null if this player version has no reported Contact.

cunning_stars integer or null

If reported, the number of stars the player has in Cunning.

null if this player version has no reported Cunning.

determination_stars integer or null

If reported, the number of stars the player has in Determination.

null if this player version has no reported Determination.

discipline_stars integer or null

If reported, the number of stars the player has in Discipline.

null if this player version has no reported Discipline.

insight_stars integer or null

If reported, the number of stars the player has in Insight.

null if this player version has no reported Insight.

intimidation_stars integer or null

If reported, the number of stars the player has in Intimidation.

null if this player version has no reported Intimidation.

lift_stars integer or null

If reported, the number of stars the player has in Lift.

null if this player version has no reported Lift.

muscle_stars integer or null

If reported, the number of stars the player has in Muscle.

null if this player version has no reported Muscle.

selflessness_stars integer or null

If reported, the number of stars the player has in Selflessness.

null if this player version has no reported Selflessness.

vision_stars integer or null

If reported, the number of stars the player has in Vision.

null if this player version has no reported Vision.

wisdom_stars integer or null

If reported, the number of stars the player has in Wisdom.

null if this player version has no reported Wisdom.

accuracy_stars integer or null

If reported, the number of stars the player has in Accuracy.

null if this player version has no reported Accuracy.

control_stars integer or null

If reported, the number of stars the player has in Control.

null if this player version has no reported Control.

defiance_stars integer or null

If reported, the number of stars the player has in Defiance.

null if this player version has no reported Defiance.

guts_stars integer or null

If reported, the number of stars the player has in Guts.

null if this player version has no reported Guts.

presence_stars integer or null

If reported, the number of stars the player has in Presence.

null if this player version has no reported Presence.

persuasion_stars integer or null

If reported, the number of stars the player has in Persuasion.

null if this player version has no reported Persuasion.

rotation_stars integer or null

If reported, the number of stars the player has in Rotation.

null if this player version has no reported Rotation.

stamina_stars integer or null

If reported, the number of stars the player has in Stamina.

null if this player version has no reported Stamina.

stuff_stars integer or null

If reported, the number of stars the player has in Stuff.

null if this player version has no reported Stuff.

velocity_stars integer or null

If reported, the number of stars the player has in Velocity.

null if this player version has no reported Velocity.

acrobatics_stars integer or null

If reported, the number of stars the player has in Acrobatics.

null if this player version has no reported Acrobatics.

agility_stars integer or null

If reported, the number of stars the player has in Agility.

null if this player version has no reported Agility.

arm_stars integer or null

If reported, the number of stars the player has in Arm.

null if this player version has no reported Arm.

awareness_stars integer or null

If reported, the number of stars the player has in Awareness.

null if this player version has no reported Awareness.

composure_stars integer or null

If reported, the number of stars the player has in Composure.

null if this player version has no reported Composure.

dexterity_stars integer or null

If reported, the number of stars the player has in Dexterity.

null if this player version has no reported Dexterity.

patience_stars integer or null

If reported, the number of stars the player has in Patience.

null if this player version has no reported Patience.

reaction_stars integer or null

If reported, the number of stars the player has in Reaction.

null if this player version has no reported Reaction.

greed_stars integer or null

If reported, the number of stars the player has in Greed.

null if this player version has no reported Greed.

performance_stars integer or null

If reported, the number of stars the player has in Performance.

null if this player version has no reported Performance.

speed_stars integer or null

If reported, the number of stars the player has in Speed.

null if this player version has no reported Speed.

stealth_stars integer or null

If reported, the number of stars the player has in Stealth.

null if this player version has no reported Stealth.

info

Holds information that powers the MMOLB front-end (the website you are probably reading this text on). You likely won't need to use this schema, aside from the info.raw_events table, which lets you see the game log message that corresponds to each row in data.events. The info.raw_events table would be in the data schema if not for a technological limitation.

info.ingests

Record of each time ingest ran.

Name Type Description
id bigint

An arbitrary numeric ID. This table's primary key.

started_at timestamp without time zone

When this ingest was started, in UTC.

finished_at timestamp without time zone or null

When this ingest finished, in UTC.

null if the ingest is ongoing or was aborted.

aborted_at timestamp without time zone or null

When this ingest was aborted, in UTC.

null if the ingest is ongoing, finished successfully, or was aborted in a way that prevented us from updating the database.

message text or null

A message attached to this ingest. Typically an error message.

null if the ingest has no message.

info.raw_events

Game event messages directly from the API, without MMOLDB processing. Useful for understanding confusing game events and diagnosing issues with your query, MMOLDB, or MMOLB.

Every event in data.events correlates with at least one of these by game_id and game_event_index. Some events correlate with a second by game_id and fair_ball_event_index.

A common way to use this table is to add the following to an existing query that uses data.events:

left join info.raw_events on raw_events.game_id=events.game_id
    and raw_events.game_event_index=events.game_event_index

Or, if you're looking at fair_ball_type and/or fair_ball_direction:

left join info.raw_events on raw_events.game_id=events.game_id
    and raw_events.game_event_index=events.fair_ball_event_index
Name Type Description
id bigint

An arbitrary numeric ID. This table's primary key.

game_id bigint

The game this raw event belongs to. References data.games.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use mmolb_game_id, which you access by joining data.games on this column.

game_event_index integer

The index of this game event (starting at 0) in its game's event log. This is used in combination with mmolb_game_id to identify a game event.

event_text text

The full text of this event, as it appeared on mmolb.com and in the API. Almost all the information in data.events was parsed from this message.

info.event_ingest_log

Informational messages MMOLDB generated while it was processing game events. This table powers the game view on the MMOLDB website. It's unlikely to be useful in queries.

Name Type Description
id bigint

An arbitrary numeric ID. This table's primary key.

game_id bigint

The game this event log belongs to. References data.games.

These IDs are not stable. You should not store these ids between queries, nor hard-code them into queries. Instead use mmolb_game_id, which you access by joining data.games on this column.

game_event_index integer or null

The index of the game event this log belogngs to (starting at 0) in its game's event log. This is used in combination with mmolb_game_id to identify a game event.

null indicates that this log item belongs to its game as a whole, and not to a specific event.

log_index integer

The index of this log item within its game event. This is used as a sort key.

log_level integer

The severity level of this log entry.

0 = Critical error 1 = Error 2 = Warning 3 = Info 4 = Debug 5 = Trace

Logs of level 2 and below are considered "issues", and they cause their game to be displayed on the "games with issues" page.

log_text text

The actual text of the log item.

info.ingest_timings

Exists entirely for debugging performance issues with ingest.

The columns are not documented, but if you choose to use them anyway be warned that some of durations overlap. db_insert_duration overlaps all the other db_insert_*_durations, db_fetch_for_check_duration overlaps all the other db_fetch_for_check_*_durations, and save_duration overlaps everything but fetch_duration.

info.version_ingest_log

Like event_ingest_log but for version-based entities (e.g. teams and players).

info.ingest_counts

Not yet used.