I'm trying to model football statistics in PostGreSQL and I have something that works but it doesn't quite feel right. Here's the problem:
I have teams, games and stats. For every game there are two teams. Each team has a single offensive statistic line that might include rushing, passing, etc. However, that offensive stat is implicitly the other team's defensive stat, e.g. if the the offensive team has 100 yards rushing in a game against the the defensive team, the defensive team gave up 100 yards rushing. It's important to track both offensive and defensive stats.
My current model has FootballTeam, FootballGame, FootballStat and FootballTeamStat as a linking table between FootballTeam and FootballStat. FootballStat has a foreign key to FootballGame. FootballTeamStat has two foreign keys, one to FootballTeam and one to FootballStat. It also has a StatTypeId which is a flag for either offensive or defensive. By doing this, I can avoid a lot of redundancy in FootballStat where I would otherwise have to have two rows for the same stat but one with an offensive flag and one with a defensive flag.
This works pretty well in my current application but it has never felt completely right. Is there a better way to do this? My database modeling experience pretty much is limited to projects I've done myself after reading Database Design for Mere Mortals and while this seems to follow most of my experience there, I'm not sure it's the best way.
EDIT: Updated to make it generic instead of league specific.
You're on the right track, I'd just recommend naming the tables a little better. FootballStat and FootballTeamStat read as containing statistics that existed with and without a Team context. Here's what I spec'd based on your post:
IE: DEF: Defensive, OFF: Offensive
IE: 1, OFF, Rushing
IE: 1, 1, 1, 100
I realize that offensive and defensive stats are important, but if a stat will always be associated as offensive and defensive - you could get away with logging only the offensive stats & using SQL to calculate the defensive ones. IE: If Offensive Rushing of 100 yards means a defensive loss of 100 yards, do you benefit from storing the defensive info or should you create the mapping in the db so you can get SQL to reverse the values via query or view?