属性の最大数が不明なエンティティを実装する方法は?


12

私は野球シミュレーションプログラムを設計していますが、boxscoreスキーマの設計で問題に遭遇しました。私が抱えている問題は、各イニングで得点されたランの数を追跡したいということです。実際のプログラムでこれを行う方法は、演奏されるイニングごとに大きくなる動的配列を使用することです。

野球の試合に不慣れな人にとっては、9回のイニングの終わりに試合がまだ結ばれていない限り、試合は通常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の代わりにSequencesを使用することを知っています。手元の正しい構文を思い出せないので、それに応じて翻訳してください。


ハハ、私は私のものを書くまであなたの答えを意図的に読まなかったのが好きです。いいね
jcolebrand

この答えをありがとう、それは理にかなっており、私がボックススコアスキーマを実装する方法になります。
フィリップロンバルディ

4

コラムがあるだけで何も悪いことはないと思う

inning_score int[]

1〜9およびそれ以降。これは、配列を使用するのが妥当な数少ない場所の1つです。


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についての何かになるように実際に2番目のテーブルを調整します。ゲームテーブルからイニングを非正規化する方法を示したかっただけです。これが私のプロジェクトである場合、モデルがそのように流れるように調整します。HTH。YMMV。

また、私はTSQLの男ですが、以下に示す概念は私の概念を説明するのに非常にうまく機能すると思います。言語セマンティクスはおそらく並ばないでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.