2016-01-09 41 views
3

我有3個表(SQLAlchemy類):Team,Game和GameObserver。每場比賽有2個球隊(進攻&防守),但有許多觀察隊。SQLAlchemy - 如何查詢3個表(帶關聯表)

什麼查詢會返回所有攻擊性團隊郵件[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') 

一個解決方案,我發現作品是:

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() 

然而,我懷疑有更好的方法來做到這一點使用連接。有沒有人有更好的方法?

+0

你願意有一個非重複的團隊名單,或每個實際的遊戲觀察記錄嗎? –

+0

我希望輸出包含2列(觀察者團隊電子郵件和遊戲ID)和1行爲每個觀察員遊戲。所以我猜這是後者。 – user2719905

回答

2

這應該爲每個符合條件的GameObserver記錄返回一行。

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() 
+0

太棒了!這很接近...只有改變是別名需要從sqlalchemy.orm而不是sqlalchemy導入。 我很好奇哪種方法(聯接或非聯接)更有效。他們都產出相同的產出,但幕後發生了什麼?隨着應用程序的擴展,這會帶來更好的性能?謝謝,布倫丹! – user2719905