回答

收藏

SQLAlchemy联接来自同一表的多个列

技术问答 技术问答 195 人阅读 | 0 人回复 | 2023-09-14

class Match(Base):1 J/ S: |  l: ^5 }
tablename = ‘matches’; g1 K6 o, @5 q6 L" g% ?
    id = Column(Integer, primary_key=True)
* i( k" z+ \& }; x8 T    date = Column(Date, nullable=False)
% B$ j6 J$ ~8 q( H, |2 d" O    time = Column(Time, nullable=True)0 \4 @  S" B- t
    league_id = Column(ForeignKey('leagues.id'), nullable=False, index=True)
. ]  v, O- o8 Z5 x  |+ X    league = relationship('League', backref='matches'): X" x" b7 p  i/ Q& i, @
    type = Column(enums.matches_types)/ Y3 f- K6 h; g1 g0 V" j
    home_team_id = Column(ForeignKey('teams.id'), nullable=False, index=True)
" f( K3 u& U% e4 E5 H" u    home_team = relationship('Team', foreign_keys=[home_team_id], backref='home_matches')
  b# F, t; ^7 ]& q2 D    away_team_id = Column(ForeignKey('teams.id'), nullable=False, index=True)
. N  g$ Y  t- w; P8 G& u+ e; _2 s# u" z, i9 O+ A0 u, N; Y
class Team(Base):. ^' p) K' W" `  _# G5 Y9 [
    __tablename__ = 'teams'. {0 `$ ?# e; J1 ]% x. B+ J9 u5 C
    id = Column(Integer, primary_key=True)& z/ J# P- `8 p  q+ j9 S' s5 K
    name = Column(String, nullable=False)3 H% I, E$ _* Y% ]/ S
    country_id = Column(ForeignKey('countries.id'), nullable=False, index=True)
& G# R9 f/ |& [. Z1 t# B1 g* |    country = relationship('Country', backref='teams')- }9 l% j, m0 Q' n  X; q8 p0 q
我需要编写一个查询,该查询将列和团队表连接在一起,以显示本地和客队的团队信息。7 s2 N6 c- Q0 [# B: p. t
Session.query(Match.date, Match.home_team.name, Match_away_team.name).joins(Team)
. q- m3 ]% `6 h9 X$ C( J2 _  y) ~这返回 Can't determine join between 'matches' and 'teams'; tables have more than' R4 }& L# ~+ c, ~
one foreign key constraint relationship between them. Please specify the
: `+ ]7 V, W& M( x$ d" C4 m'onclause' of this join explicitly. w3 Q. t4 N5 H  t- l6 R7 Z' }
                  r7 o3 i1 }- v. D  F( n
解决方案:
  j; f; v7 f7 a1 J6 F               
8 _' X3 P7 d0 G# B. G/ r# `+ y+ G2 h1 y; i

' n- d) C# E: |# [                首先,您的代码不起作用的原因是因为SQLAlchemy不知道您是否要Team通过viahome_team或加入away_team,因此您必须告诉它。此外,您需要加入Team两次,这使事情变得更加复杂。
: `; ~7 g5 X4 w  s5 w( v使用joinedload以下命令可以更轻松地完成此操作:" \. t+ D! ~" z( ]* H
matches = session.query(Match).options(joinedload(Match.home_team),; j& c' Y0 d. x
                                       joinedload(Match.away_team))
6 r" _  H$ `$ A# h# g& u( q( m* F- {( Gfor m in matches:4 n0 I# I- N9 N; S# e' L1 y
    print m.date, m.home_team, m.away_team
+ J1 S7 w* n) e$ k2 ]& O3 J9 Am.home_team并且m.away_team将在相同的查询被装载m使用JOIN。
2 L2 v* w3 Y  Z0 G& u: F" v, y如果你坚持使用一个明确的.join(),你得别名的Team实体(未测试):5 F; k4 y5 s/ P* d6 t+ ]6 J: w- K
home = aliased(Team)
' |+ |% K* _, ^+ R! n+ ?away = aliased(Team)- n1 v2 M( F" M$ G- M
q = session.query(Match.date, home, away).join(home, Match.home_team) \
8 A* b. n$ V6 l8 C* j0 j; N: Q                                         .join(away, Match.away_team)* s' |- `( X! W7 J! g3 p. v2 l
for date, home_team, away_team in q:
+ I- s* Z! R3 m4 D% E  D: R    print date, home_team, away_team
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则