Implementieren einer Entität mit einer unbekannten maximalen Anzahl von Attributen

12

Ich entwerfe ein Baseball-Simulationsprogramm und bin auf ein Problem beim Entwurf des Boxscore-Schemas gestoßen. Das Problem, das ich habe, ist, dass ich verfolgen möchte, wie viele Läufe in jedem Inning erzielt werden. Die Art und Weise, wie ich dies im eigentlichen Programm mache, besteht darin, ein dynamisches Array zu verwenden, das mit jedem gespielten Inning wächst.

Für diejenigen, die mit dem Baseballspiel nicht vertraut sind, sind Spiele normalerweise neun Innings lang, es sei denn, das Spiel ist noch am Ende des 9. Innings unentschieden. Baseball-Spiele haben daher eine unbestimmte Länge, was bedeutet, dass ich die Datenbank nicht so gestalten kann, dass sie nur 9 Spalten für die Läufe enthält, die pro Inning erzielt wurden (technisch gesehen 18 (9-Innings * 2-Teams). Eine Idee, die ich hatte, ist die Serialisierung des Arrays Ich weiß jedoch nicht, ob dies eine gute Technik ist, und habe mich gefragt, ob jemand eine bessere Idee hat.

Falls es wichtig ist, ist die Datenbank, um die ich mich entwickle, PostgreSQL.

Anregungen sind sehr dankbar! Vielen Dank!

Philip Lombardi
quelle

Antworten:

7

Du könntest das tun. Dies würde eine gute Leistung für Spiele mit normaler Spieldauer ermöglichen, während Sie auch Spiele mit langer Spieldauer speichern können.

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

Sie könnten jede einzelne Kombination aus Spiel, Team und Inning weiter normalisieren und eine Reihe bilden. Dies würde Ihnen so viele Innings erlauben, wie der InningId-Datentyp erlauben würde.

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

Bearbeiten : Ich weiß, dass PostgreSQL Sequenzen anstelle von IDENTITÄT verwendet. Ich kann mich nicht sofort an die richtige Syntax erinnern. Übersetzen Sie daher entsprechend.

Eric Humphrey - Lotsahelp
quelle
haha, ich mag es, dass ich deine Antwort absichtlich nicht gelesen habe, bis ich meine geschrieben habe und wir uns sehr nahe sind. Nett.
Jcolebrand
Vielen Dank für diese Antwort, es ist sinnvoll und wird sein, wie ich das Box-Score-Schema implementiere.
Philip Lombardi
4

Ich glaube nicht, dass irgendetwas falsch ist, wenn man nur eine Kolumne hat

inning_score int[]

für 1 bis 9 und darüber hinaus. Dies ist einer der wenigen Orte, an denen die Verwendung eines Arrays sinnvoll sein kann.

Peter Eisentraut
quelle
3

Was ich hier sehe, ist also ein wenig widersprüchlich, weil Innings nicht wirklich direkt ein Attribut von Spielen sind, außer indirekt. Aber vielleicht bin das nur ich. Ich würde persönlich eher so etwas wie eine RunsScored-Tabelle vorschlagen und sie auf irgendeine Art mit einer GamesHeader-Tabelle verknüpfen.

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'

Das gibt dir das maximale Inning, das für ein bestimmtes Spiel gespielt wird, und du kannst es mit PlayerID -> TeamID weiter verfeinern, um mehr Details herauszufinden, wenn du möchtest. Was das sein könnte, weiß ich nicht.

Ich würde diese zweite Tabelle wahrscheinlich tatsächlich so verfeinern, dass sie nicht mit RunsScored bewertet wird, sondern mit AtBat, denn genau das verfolgen Sie. Ich wollte nur zeigen, wie man das Inning vom Spieltisch weg denormalisieren kann. Ich würde mein Modell so anpassen, dass es so läuft, wäre dies mein Projekt. HTH. YMMV.

Beachten Sie auch, dass ich ein TSQL-Typ bin, aber ich denke, dass die unten aufgeführten Konzepte recht gut funktionieren, um mein Konzept zu erklären. Die Sprachsemantik wird wahrscheinlich nicht anstehen.

jcolebrand
quelle