3

我有三张桌子:

class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)

class Bar(Base):
    __tablename__ = 'bar'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)

class Baz(Base):
    __tablename__ = 'baz'
    id = Column(Integer, primary_key=True)
    foo_id = Column(ForeignKey('foo.id'), nullable=True)
    foo = relationship('Foo', backref='bazes')
    bar_id = Column(ForeignKey('bar.id'), nullable=True)
    bar = relationship('Bar', backref='bazes')
    name = Column(String(100), nullable=False)

所以 Baz 有返回 Foo 和 Bar 的外键。

假设 Foo 有三行,名称分别为 a、b 和 c。假设 Bar 有三行,名称分别为 x、y 和 z。

我想执行一个查询,以获取给定 Foo 和 Bar 在 Baz 中的行数,即使答案是 0。返回值是这样的:

('a', 'x', 12)
('a', 'y', 3)
('a', 'z', 0)
('b', 'x', 9)
('b', 'y', 0)
('b', 'z', 1)
('c', 'x', 3)
('c', 'y', 6)
('c', 'z', 2)

对于单个相关表,我了解如何对 Baz 进行子查询(按 Baz.foo_id 分组),然后对 Foo 进行查询,该查询与 Baz 保持外连接。但是对于两个相关的表,我很茫然。是否可以在 sqlalchemy 中执行此查询?

4

1 回答 1

1

为此,我通常使用子查询。这是我将生成的 SQL:

SELECT foo.name, bar.name, (SELECT COUNT('*') FROM baz WHERE baz.foo_id=foo.id AND baz.bar_id=bar.id) FROM foo, bar

SQLAlchemy 中的一个:

count_query = session.query(func.count('*')).filter(Baz.foo_id==Foo.id).filter(Baz.bar_id==Bar.id).correlate(Bar).correlate(Foo).as_scalar()
query = session.query(Foo.name, Bar.name, count_query)

对于这个查询与巧妙组合 OUTER JOIN 的查询相比,我不是专家,所以我不确定这是否更慢。否则我会尝试类似的东西:

FROM foo LEFT OUTER JOIN baz ON foo.id=baz.foo_id RIGHT OUTER JOIN bar ON bar.id=baz.bar_id

我不确定这会产生你需要的东西,现在我只有可用的 sqlite 不支持RIGHT OUTER JOIN,所以我无法测试它。但是我已经验证了上述查询会生成您想要的结果。

于 2013-10-04T12:03:25.810 回答