Come implementare un'entità con un numero massimo di attributi sconosciuto?


12

Sto progettando un programma di simulazione di baseball e ho riscontrato un problema con la progettazione dello schema di boxscore. Il problema che ho è che voglio tenere traccia di quante piste sono segnate in ciascun inning. Il modo in cui lo faccio nel programma reale è usare un array dinamico che cresce per ogni inning giocato.

Per coloro che non hanno familiarità con il gioco del baseball, i giochi sono generalmente lunghi nove inning a meno che il gioco non sia ancora legato alla fine del nono inning. I giochi di baseball, quindi, hanno una lunghezza indeterminata, il che significa che non posso progettare il database in modo da avere solo 9 colonne per le piste segnate ogni inning (ben 18 tecnicamente (9 innings * 2 squadre). Un'idea che ho avuto è quella di serializzare l'array e codificarlo come Base64 prima di memorizzarlo nel database. Tuttavia, non so se questa sia una buona tecnica da usare e mi chiedevo se qualcuno avesse un'idea migliore.

Nel caso sia importante, il database che sto sviluppando è PostgreSQL.

Tutti i suggerimenti sono molto apprezzati! Grazie!

Risposte:


7

Potresti farlo. Consentirebbe buone prestazioni per i giochi di durata normale, consentendo allo stesso tempo di memorizzare anche giochi di lunga durata.

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)
)

Potresti ulteriormente normalizzare e avere una riga per ogni combinazione unica di gioco, squadra e inning. Ciò consentirebbe tanti innings quanti sarebbero consentiti dal tipo di dati 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)
)

Modifica : so che PostgreSQL usa Sequenze invece di IDENTITÀ, non ricordo la sintassi corretta dalla mano, quindi traduci di conseguenza.


ahah, mi piace che di proposito non ho letto la tua risposta finché non ho scritto la mia e siamo molto vicini all'altro. Bello.
jcolebrand

Grazie per questa risposta, ha senso e sarà il modo in cui implementerò lo schema dei punteggi delle caselle.
Philip Lombardi,

4

Non penso che ci sia qualcosa di sbagliato nel solo avere una colonna

inning_score int[]

da 1 a 9 e oltre. Questo è uno dei pochi posti in cui l'utilizzo di un array potrebbe essere ragionevole.


3

Quindi quello che vedo qui è un po 'contraddittorio perché gli inning non sono in realtà direttamente un attributo dei giochi, tranne indirettamente. Ma forse sono solo io. Personalmente suggerirei qualcosa di più simile a una tabella RunsScored, e vorrei riportarlo a una tabella GamesHeader, di qualche tipo, quindi considera:

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'

Questo ti darà il massimo Inning giocato per un determinato gioco e puoi perfezionarlo con PlayerID -> TeamID per scoprire ulteriori dettagli se lo desideri. Quali potrebbero essere quelli non sono sicuro.

Probabilmente rifinirei la seconda tabella in modo che non sia RunsScored ma qualcosa su AtBat perché è proprio quello che stai monitorando. Volevo solo mostrare come potresti denormalizzare l'inning lontano dal tavolo da gioco. Modificherei il mio modello per fluire così, se questo fosse il mio progetto. HTH. YMMV.

Nota anche che sono un tipo TSQL, ma penso che i concetti espressi di seguito funzionino abbastanza bene per spiegare il mio concetto. La semantica della lingua probabilmente non si allinea.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.