Предложение выше является хорошим. На самом деле я бы добавил два столбца в таблицу PlayerTeam: год и суррогатный ключ, который будет вашим основным ключом.
Думайте об этом так: таблица игроков описывает всех игроков, таблица команд описывает все команды, а таблица PlayerTeam описывает отношения между игроками и командами. Эти отношения должны также включать, когда игроки были в данной команде.
Есть несколько других вещей, которые вы можете рассмотреть. Возможно ли, чтобы игрок покинул команду и не присоединился к другой? Например, может ли игрок уйти в отставку или взять годовой отпуск, и вы хотите записать это? Если это так, вы можете рассмотреть возможность добавления еще одного столбца даты в таблицу PlayerTeam, указывающую, когда игрок покинул данную команду.
Если вас беспокоит сложность вызовов, вы можете подумать о создании таблиц таким образом, чтобы вы могли присоединяться к ним с помощью естественных объединений. Естественные объединения, если они доступны, - это объединения двух таблиц, в которых есть столбцы с одинаковыми именами. Обычно мне нравится решать эту проблему следующим образом (прошу прощения за псевдокод):
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;
Или что-то на этот счет. Это может быть не особенно эффективно (возможно, вы захотите запустить «объяснение» в запросе выбора), но его довольно просто обработать.