我有一个我正在尝试构建的查询。查询似乎在部分工作,查询的单独部分返回正确数量的元素。但是,组合查询返回空结果集,这是不正确的。
注意:我知道查询1和2不需要and_,但我想确保and_按预期工作。
查询1 :
SQLAlchemy Query
session.query(Lobby).filter(
and_(
Lobby.id == spectator_table.c.lobby_id,
spectator_table.c.player_id == player.steamid
)
).all()
生成的SQL
SELECT lobby.id AS lobby_id, lobby.name AS lobby_name, lobby.owner_id AS lobby_owner_id
FROM lobby, spectator
WHERE lobby.id = spectator.lobby_id AND spectator.player_id = ?
查询2 :
SQLAlchemy Query
session.query(Lobby).filter(
and_(
Lobby.id == Team.lobby_id,
LobbyPlayer.team_id == Team.id,
LobbyPlayer.player_id == player.steamid
)
).all()
生成的SQL
SELECT lobby.id AS lobby_id, lobby.name AS lobby_name, lobby.owner_id AS lobby_owner_id
FROM lobby, team, lobby_player
WHERE lobby.id = team.lobby_id AND lobby_player.team_id = team.id AND lobby_player.player_id = ?
合并查询:
SQLAlchemy Query
session.query(Lobby).filter(
or_(
and_(
Lobby.id == Team.lobby_id,
LobbyPlayer.team_id == Team.id,
LobbyPlayer.player_id == player.steamid
), and_(
Lobby.id == spectator_table.c.lobby_id,
spectator_table.c.player_id == player.steamid
)
)
).all()
生成的SQL
SELECT lobby.id AS lobby_id, lobby.name AS lobby_name, lobby.owner_id AS lobby_owner_id
FROM lobby, team, lobby_player, spectator
WHERE lobby.id = team.lobby_id AND lobby_player.team_id = team.id AND lobby_player.player_id = ? OR lobby.id = spectator.lobby_id AND spectator.player_id = ?
模特
spectator_table = Table('spectator', Base.metadata,
Column('lobby_id', Integer, ForeignKey('lobby.id'), primary_key=True),
Column('player_id', Integer, ForeignKey('player.steamid'),
primary_key=True
),
)
class Lobby(Base):
__tablename__ = 'lobby'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
owner_id = Column(Integer, ForeignKey('player.steamid'), nullable=False,
unique=True
)
teams = relationship("Team", backref="lobby",
cascade='save-update,merge,delete'
)
spectators = relationship("Player", secondary=spectator_table)
class Team(Base):
__tablename__ = 'team'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
lobby_id = Column(Integer, ForeignKey('lobby.id'), nullable=False)
players = relationship("LobbyPlayer", backref="team",
cascade='save-update,merge,delete,delete-orphan'
)
class LobbyPlayer(Base):
__tablename__ = 'lobby_player'
team_id = Column(Integer, ForeignKey('team.id'), primary_key=True)
player_id = Column(Integer, ForeignKey('player.steamid'), primary_key=True)
player = relationship("Player", uselist=False)
cls = Column(Integer)
class Player(Base):
__tablename__ = 'player'
steamid = Column(Integer, primary_key=True)
感谢您的帮助!
答案 0 :(得分:8)
我在SA 0.7.9上看到了同样的问题
似乎在讨厌的是,括号没有按照您希望的方式正确应用。我使用self_group()来完成这项工作,但事情是你不应该使用它。以下是文档 self_group。我认为应该有一个更好的答案,然而,这应该让你去。
query = session.query(Lobby).filter(
((Lobby.id == Team.lobby_id) &
(LobbyPlayer.team_id == Team.id) &
(LobbyPlayer.player_id == player.steamid)).self_group() |
((Lobby.id == spectator_table.c.lobby_id) &
(spectator_table.c.player_id == player.steamid)).self_group()).all()
生成的sql在下面,我相信你正在追求的目标。
SELECT lobby.id AS lobby_id, lobby.name AS lobby_name, lobby.owner_id AS lobby_owner_id
FROM lobby, team, lobby_player, spectator
WHERE (lobby.id = team.lobby_id AND lobby_player.team_id = team.id AND lobby_player.player_id = ?) OR (lobby.id = spectator.lobby_id AND spectator.player_id = ?)
答案 1 :(得分:4)
Tony,我从来不知道self_group(),最优秀!
TronPaul, 您可以使用self_group()来添加parens和ClauseElements,例如:
query = session.query(Invoice).join(CustomerQuote).reset_joinpoint()
selections = [1,2,3,4,5,6]
select_ids = Invoice.invoice_id.in_(selections).self_group()
ands = and_(CustomerQuote.customer_id==33,
CustomerQuote.invoice_date>=low_date,
CustomerQuote.invoice_date<=hi_date).self_group()
query = query.filter(or_(select_ors, ands))
SELECT invoice.invoice_id AS invoice_invoice_id, [etc etc....]
FROM invoice INNER JOIN customer_quote ON
customer_quote.customer_quote_id = invoice.customer_quote_id
WHERE (invoice.invoice_id IN (1,2,3,4,5)) OR
(customer_quote.customer_id = 33 AND
invoice.invoice_date >= '2012-01-01' AND
invoice.invoice_date <= '2012-12-31')
详细说明Tony的答案:self_group()对于“二进制”表达式以外的子句分组很有用,它适用于任何ClauseElement。