Reputation: 33
I have 3 tables (SQLAlchemy classes): Team, Game, and GameObserver. Each game has 2 playing teams (offense & defense) but many observing teams.
What query would return all observers (teams) of games where the offensive team email was [email protected]?
class Team(db.Model):
id = db.Column(db.Integer(), primary_key=True)
email = db.Column(db.String(120), index=True, unique=True)
class Game(db.Model):
id = db.Column(db.Integer, primary_key=True)
offense_id = db.Column(db.Integer(), db.ForeignKey('team.id'))
defense_id = db.Column(db.Integer(), db.ForeignKey('team.id'))
offense = db.relationship('Team',
foreign_keys=[offense_id], backref='offensive_games')
defense = db.relationship('Team',
foreign_keys=[defense_id], backref='defensive_games')
class GameObserver(db.Model):
id = db.Column(db.Integer, primary_key=True)
observer_id = db.Column(db.Integer(), db.ForeignKey('team.id'))
game_id = db.Column(db.Integer(), db.ForeignKey('game.id'))
game = db.relationship('Game',
foreign_keys=[game_id], backref='game_watchers')
observer = db.relationship('Team',
foreign_keys=[observer_id], backref='watched_games')
One solution that I found works is:
db.session.query(Game.id, Team.email).filter(GameObserver.observer_id ==
Team.id).filter(GameObserver.game_id == Game.id).filter(Game.offense.has(email =
'[email protected]')).all()
However, I suspect there is a better way to do this using joins. Does anyone have a better approach?
Upvotes: 3
Views: 1973
Reputation: 37509
This should return a row for each GameObserver record that matches your criteria.
from sqlalchemy.orm import aliased
off_Team = aliased(Team)
obs_Team = aliased(Team)
results = db.session.query(obs_Team.email, Game.id)\
.select_from(GameObserver)\
.join(Game)\
.join(obs_Team, GameObserver.observer)\
.join(off_Team, Game.offense)\
.filter(off_Team.email == '[email protected]')\
.all()
Upvotes: 2