3

作成しようとしているクエリがあります。クエリは部分的に機能しているようで、クエリの別々の部分の両方が正しい数の要素を返します。ただし、結合されたクエリは空の結果セットを返しますが、これは正しくありません。

注: クエリ 1 と 2 に and_ が必要ないことはわかっていますが、and_ が期待どおりに機能していることを確認したかったのです。

クエリ 1 :

  • SQLAlchemy クエリ

    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 クエリ

    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 クエリ

    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)

助けてくれてありがとう!

4

2 に答える 2

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 = ?)
于 2012-11-14T01:05:08.340 に答える
6

トニー、私は self_group() についてまったく知りませんでした。

TronPaul さん、self_group() を使用して括弧と 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')

トニーの答えを詳しく説明すると、self_group() は「バイナリ」式以外の句をグループ化するのに役立ち、任意の ClauseElement で機能します。

于 2012-11-27T18:50:14.377 に答える