上記の提案は良いものです。実際には、PlayerTeamテーブルに2つの列を追加します.1年と主キーとして機能するサロゲートキーです。
このように考える:プレーヤテーブルはすべてのプレーヤを記述し、チームテーブルはすべてのチームを記述し、PlayerTeamテーブルはプレーヤとチームの関係を記述する。この関係には、プレイヤーが所属チームに所属していた時期も含まれている必要があります。
他にもいくつか検討したいことがあります。プレーヤーがチームを離れ、別のチームに参加していない可能性はありますか?たとえば、プレイヤーは退職したり1年を取ることができますか?これを記録しますか?もしそうなら、プレイヤーが所属チームを離脱した日時を示す別の日付列をPlayerTeamテーブルに追加することをお勧めします。
コールが複雑になることが心配な場合は、自然な結合を使用してテーブルに参加できるようにテーブルを作成することを検討してください。 Natural結合は、使用可能な場合は、同じ名前の列がある2つの表の結合です。一般的に、私はこの問題に対処好きなように、この(擬似コードはご容赦ください)のようなものです:
PlayerTable:
(int) player_id PRIMARY KEY AUTOINCREMENT
...
other data
TeamTable:
(int) team_id PRIMARY KEY AUTOINCREMENT
...
other data
PlayerTeamTable:
(int) player_team_id PRIMARY KEY AUTOINCREMENT
(int) player_id FOREIGN KEY references PlayerTable(player_id)
(int) team_id FOREIGN KEY references TeamTable(team_id)
(datetime) joined_team
(datetime) left_team
この方法で、あなたは現在、特定のチームの一部であるすべての人を見つけるために、単純なクエリを実行することができます:
select * from PlayerTable natural join TeamTable, PlayerTeamTable where team_name = 'Liverpool' and left_team = NULL;
またはその旨。これは特に効率的ではないかもしれません(selectクエリで "explain"を実行することもできます)が、処理は非常に簡単です。
私は似たようなことをしますが、サロゲートプライマリキーを使用して、単純にPlayer、Team、Yearに複合ユニークキーを作成します。理由はわかりません - 私は複数列の主キーが嫌いです。 –
ええ、それは私の方向ですが、クエリは乱雑です。チームのすべての選手を得るために、私はすべてのユニークな値を取得する必要があります。サロゲートキー、チームとプレーヤーの外部キー、チームプレーヤーのコンボに関するユニークな制約、サロゲートキーを参照する新しい年テーブルについてはどうでしょうか? –
与えられたジャンクションテーブルは、私にとって、マルチカラムPKを避けるための唯一の例外です。しかし、サロゲートキーのソリューションは少なくとも良いものです。 – RolandTumble