You don't need a third table - reference the teams directly from the match
table:

Just to clarify, the {team1_id, team2_id}
should not be a key, to allow the same pair of teams to be engaged in more than one match. And of course, it goes without saying you need appropriate FKs and a CHECK(team1_id <> team2_id)
.
To get the matches played by the given team, you'd need..
SELECT ... WHERE team1_id = :given_team_id OR team2_id = :given_team_id
...so you need indexes on both team IDs, as denoted by I1
and I2
in the diagram above.
Also, consider making these indexes wider for performance reasons. For example, if your only fetch a limited subset of fields...
SELECT team1_id, team2_id FROM ...
...and widen the indexes to cover these fields (I1: {team1_id, team2_id}
and I2: {team2_id, team1_id}
), the DBMS won't have to touch your table heap at all to satisfy the query.
Alternatively, you could consider using a natural key, for example:

This would allow you to eliminate one of the indexes (the one under the surrogate PK: {match_id}
), but would of course make any downstream FKs "fatter", which may or may not be a good thing depending on what you are trying to accomplish.
Depending on your querying needs, you may fiddle with the order of PK fields:
- For example, if majority of your queries ask: "give me matches played in the last X days", consider moving
match_date
to front.
- If majority of your queries ask for matches played at any time, keep it in the back.
- If both, then you'd need an additional index.
BTW, having a third table {match_id, team_id}
is appropriate for matches that can be played by more than two teams (such as sailing). It also has an unfortunate feature of allowing only one or even zero teams - which is something you'll probably need to guard against in a non-declarative manner.
The design above ensures there are exactly two teams.