Як реалізувати сутність з невідомою максимальною кількістю атрибутів?


12

Я розробляю програму моделювання бейсболу, і у мене виникли проблеми з розробкою схеми boxscore. Проблема в мені полягає в тому, що я хочу відстежити, скільки пробіжок забито в кожному іннінгу. Те, як я це роблю в реальній програмі, - це використовувати динамічний масив, який зростає для кожного відтворення.

Для тих, хто не знайомий з грою в бейсбол, ігри зазвичай тривають дев'ять подач, якщо гра не зв'язана ще в кінці 9-го іннінгу. Отже, бейсбольні ігри мають невизначену довжину, що означає, що я не можу спроектувати базу даних, щоб мати лише 9 стовпців для пробіжок, набраних за кожну іннінг (технічно добре 18 (9-подач * 2 команди). Однією з моїх ідей є серіалізація масиву і кодувати його як Base64, перш ніж зберігати його в базі даних. Однак, я не знаю, чи це хороша методика для використання, і мені було цікаво, чи є хтось кращий задум.

У випадку, якщо це має значення, база даних, яку я розвиваю, - це PostgreSQL.

Будь-які пропозиції дуже вдячні! Дякую!

Відповіді:


7

Ви могли це зробити. Це дозволить забезпечити хороші показники для ігор звичайної тривалості, а також дозволяти зберігати тривалі ігри.

CREATE TABLE InningRuns (
    GameId INT NOT NULL REFERENCES [...],
    Team CHAR(4) NOT NULL, --'Home','Away'
    Inning1 TINYINT, --Seeing how more than 255 runs are not really possible in an inning
    Inning2 TINYINT,
    [...],
    Inning9 TINYINT,
    ExtraInnings XML | TINYINT[] | VARBINARY | ETC., --Use to hold any runs in extra innings.
    PRIMARY KEY (GameId, Team)
)

Ви можете далі нормалізувати і мати ряд для кожної унікальної комбінації гри, команди та іннінгу. Це дозволить отримати стільки подань, скільки дозволить тип даних InningId.

CREATE TABLE InningRuns (
    InningRunId INT IDENTITY PRIMARY KEY,
    GameId INT NOT NULL REFERENCES [...],
    Team CHAR(4) NOT NULL, --'Home','Away'
    InningId TINYINT, --Seeing how more than 255 innings might be excessive
    Runs TINYINT,
    UNIQUE (GameId, Team, InningId)
)

Редагувати : Я знаю, що PostgreSQL використовує послідовності замість IDENTITY, я не пригадую правильний синтаксис від руки, тому перекладайте відповідно.


ха-ха, мені подобається, що я навмисно не прочитав вашої відповіді, поки я не написав свою, і ми дуже близькі до іншого. Приємно.
jcolebrand

Дякую за цю відповідь, це має сенс і буде, як я впроваджую схему шкали балів.
Філіп Ломбарді

4

Я не думаю, що немає нічого поганого в тому, щоб мати колонку

inning_score int[]

від 1 до 9 і далі. Це одне з небагатьох місць, де використання масиву може бути розумним.


3

Тож те, що я бачу тут, є трохи суперечливим, тому що подачі насправді не є безпосередньо атрибутом ігор, за винятком непрямого. Але, можливо, це тільки я. Я особисто запропонував би щось більше, як таблицю RunsScored, і попросив би це посилання назад до таблиці GamesHeader, тому врахуйте:

CREATE TABLE GamesHeader (
    GameID     INT IDENTITY(1,1),
    HomeTeamID INT,  --FK to teams table, naturally
    AwayTeamID INT,  --FK to teams table, naturally
    FinalInningsCount BYTE,  -- for faster reporting after the game is over
    FinalHomeScore BYTE,     -- for faster reporting after the game is over
    FinalAwayScore BYTE,     -- for faster reporting after the game is over
    --Other attribs
)

CREATE TABLE RunsScored (
    RunsScoredID BIGINT IDENTITY(1,1), -- for faster reverse traversal, possibly. May not be needed, this depends on your setup, as the normalization will show a composite key anyways
    PlayerID INT,   --FK to players table naturally
    GameID INT,     --FK to GamesHeader table naturally
    Inning BYTE, --wait for the payoff
    RunsEarned,     --because you may want to track this by the player ... really the problem is that there's not a single naturalized setup for this, so you may be intersecting this table to another stats table elsewhere. idk, it depends on your model. I'm going for fairly simplistic atm. Wanted to demonstrate something else entirely, but this needs to be accounted for.
     -- other attribs
)

SELECT MAX(r.Inning) FROM RunsScored r JOIN GamesHeader g ON g.GameID = r.GameID WHERE GameID = 'x'

Це дасть вам максимальний розмір гравця для певної гри, і ви можете додатково уточнити програмою PlayerID -> TeamID, щоб дізнатися більше деталей, якщо хочете. Що це може бути, я не впевнений.

Я, мабуть, фактично уточнив цю другу таблицю, щоб вона не була RunsScored, а щось про AtBat, тому що це дійсно те, що ви відстежуєте. Я просто хотів показати, як можна денормалізувати подачу подалі від ігрового столу. Я б налаштовував свою модель на течію так, якби це був мій проект. HTH. YMMV.

Також зауважте, що я хлопець TSQL, але я думаю, що поняття, викладені нижче, досить добре працюють для пояснення моєї концепції. Мовна семантика, ймовірно, не вирівняється.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.