SQL Alchemy奇怪的行为从同一个表中加入多个列

Posted

技术标签:

【中文标题】SQL Alchemy奇怪的行为从同一个表中加入多个列【英文标题】:SQL Alchemy Strange behaviour Join Multiple Columns from same table 【发布时间】:2016-04-15 21:09:18 【问题描述】:

我正在尝试执行一个查询,该查询涉及连接同一列中的两列。

这些是我的模型:

class Match(Base):
    __tablename__ = 'matches'

    id = Column(Integer, primary_key=True)
    date = Column(Date, nullable=False)
    time = Column(Time, nullable=True)
    league_id = Column(ForeignKey('leagues.id'), nullable=False, index=True)
    league = relationship('League', backref='matches')
    type = Column(enums.matches_types)
    home_id = Column(ForeignKey('teams.id'), nullable=False, index=True)
    home = relationship('Team', foreign_keys=[home_id], backref='home_matches')
    away_id = Column(ForeignKey('teams.id'), nullable=False, index=True)
    away = relationship('Team', foreign_keys=[away_id], backref='away_matches')


class Team(Base):
    __tablename__ = 'teams'

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    country_id = Column(ForeignKey('countries.id'), nullable=False, index=True)
    country = relationship('Country', backref='teams')

这是我在 SQLAlchemy 中写的:

self.db_match = Session.query(Match).join(home, Match.home).options(contains_eager(Match.home)
                        ).join(away, Match.away).options(contains_eager(Match.away)
                        ).join(Match.b_reference).options(contains_eager(Match.b_reference)
                        ).filter(home.name == self.match['home']['name']
                        ).filter(away.name == self.match['away']['name']
                        ).filter(Match.date == self.match['date'])

SQLAlchemy 对纯 SQL 的翻译如下:

SELECT teams_1.name, teams_2.name, matches.id, matches_b_reference_codes.code
FROM teams, matches JOIN teams AS teams_1 ON teams_1.id = matches.home_id 
JOIN teams AS teams_2 ON teams_2.id = matches.away_id 
JOIN matches_b_reference_codes ON matches.id = matches_b_reference_codes.match_id 
WHERE teams_1.name = 'Portland Trail Blazers' AND teams_2.name = 'Miami Heat' AND matches.date = '2011-01-09';

但这正是我需要的:

SELECT teams_1.name, teams_2.name, matches.id, matches_b_reference_codes.code
**FROM matches JOIN teams AS teams_1 ON teams_1.id = matches.home_id** 
JOIN teams AS teams_2 ON teams_2.id = matches.away_id 
JOIN matches_b_reference_codes ON matches.id = matches_b_reference_codes.match_id 
WHERE teams_1.name = 'Portland Trail Blazers' AND teams_2.name = 'Miami Heat' AND matches.date = '2011-01-09';

【问题讨论】:

什么是home,什么是awayMatch.homeMatch.away 是什么? 抱歉,模型出现错误。我更正了。 【参考方案1】:

您错误地使用了contains_eager。加入别名时需要指定alias 参数:

home = aliased(Team)
away = aliased(Away)
Session.query(Match).join(home, Match.home) \
                    .options(contains_eager(Match.home, alias=home)) \
                    .join(away, Match.away) \
                    .options(contains_eager(Match.away, alias=away)) \
                    ... \
                    .filter(...)

【讨论】:

以上是关于SQL Alchemy奇怪的行为从同一个表中加入多个列的主要内容,如果未能解决你的问题,请参考以下文章

在pygame中加入多处理

在 SQL Alchemy ORM 中使用辅助连接

在 Django 中加入多对多表

天蓝色专用 sql 池 (sqldw) 可序列化表提示语句奇怪的行为

带有 INSERT 和 WHERE NOT EXISTS 的奇怪 SQL 行为

使用奇怪的查询优化器行为加入 SQL Server 中的视图