Bagaimana cara mengimplementasikan suatu entitas dengan jumlah atribut maksimum yang tidak diketahui?

12

Saya merancang program simulasi bisbol dan saya telah mengalami masalah dengan merancang skema boxscore. Masalah yang saya miliki adalah bahwa saya ingin melacak berapa banyak skor berjalan di setiap inning. Cara saya melakukan ini dalam program yang sebenarnya adalah dengan menggunakan array dinamis yang tumbuh untuk setiap inning yang dimainkan.

Bagi mereka yang tidak terbiasa dengan permainan bisbol, permainan biasanya sembilan babak inning kecuali jika permainan terikat masih pada akhir inning ke-9. Oleh karena itu, permainan bisbol, memiliki panjang yang tidak ditentukan yang berarti saya tidak dapat mendesain database hanya memiliki 9 kolom untuk skor setiap inning (baik secara teknis 18 (9-inning * 2-tim) .Satu ide yang saya miliki adalah mengurutkan array dan menyandikannya sebagai Base64 sebelum menyimpannya dalam database. Namun, saya tidak tahu apakah ini teknik yang baik untuk digunakan dan saya bertanya-tanya apakah ada yang punya ide yang lebih baik.

Dalam hal ini penting, basis data yang saya kembangkan adalah PostgreSQL.

Setiap saran sangat dihargai! Terima kasih!

Philip Lombardi
sumber

Jawaban:

7

Anda bisa melakukan ini. Ini akan memungkinkan kinerja yang baik untuk game berdurasi normal, sementara memungkinkan Anda untuk juga menyimpan game yang berjalan lama.

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

Anda dapat menormalkan lebih lanjut dan memiliki deretan untuk setiap kombinasi permainan, tim, & inning yang unik. Ini akan memungkinkan Anda sebanyak inning sebagai datatype InningId akan memungkinkan.

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

Sunting : Saya tahu PostgreSQL menggunakan Sequences alih-alih IDENTITY, saya tidak ingat sintaks yang benar, jadi terjemahkan dengan tepat.

Eric Humphrey - lotahelp
sumber
haha, saya suka bahwa saya sengaja tidak membaca jawaban Anda sampai saya menulis jawaban saya dan kami sangat dekat dengan yang lain. Bagus.
jcolebrand
Terima kasih atas jawaban ini, masuk akal dan akan menjadi bagaimana saya menerapkan skema skor kotak.
Philip Lombardi
4

Saya tidak berpikir ada yang salah dengan hanya memiliki kolom

inning_score int[]

untuk 1 hingga 9 dan seterusnya. Itu salah satu dari sedikit tempat di mana menggunakan array mungkin masuk akal.

Peter Eisentraut
sumber
3

Jadi apa yang saya lihat di sini sedikit kontradiktif karena inning tidak benar-benar atribut game, kecuali secara tidak langsung. Tapi mungkin itu hanya aku. Saya pribadi akan menyarankan sesuatu yang lebih seperti tabel RunsScored, dan minta tautan balik ke meja GamesHeader, dari beberapa jenis, jadi pertimbangkan:

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'

Itu akan memberi Anda Inning maksimum yang dimainkan untuk gim tertentu, dan Anda dapat lebih menyempurnakan oleh PlayerID -> TeamID untuk mengetahui detail lebih lanjut jika Anda menginginkannya. Apa itu mungkin saya tidak yakin.

Saya mungkin akan benar-benar memperbaiki tabel kedua agar tidak menjadi RunsScored tetapi sesuatu tentang AtBat karena itulah yang sebenarnya sedang Anda lacak. Saya hanya ingin menunjukkan bagaimana Anda bisa mendenormalisasi inning jauh dari meja permainan. Saya akan mengubah model saya mengalir seperti itu, apakah ini proyek saya. HTH. YMMV.

Perhatikan juga bahwa saya adalah seorang pria TSQL, tapi saya pikir konsep yang diungkapkan di bawah ini bekerja cukup baik untuk menjelaskan konsep saya. Semantik bahasa mungkin tidak akan berbaris.

jcolebrand
sumber