将子查询与其父级隔离

时间:2016-07-20 20:59:44

标签: python sqlalchemy

我的模型上有一个column_property,它是次要模型上关系的计数。

membership_total = column_property(
        select([func.count(MembershipModel.id)]).where(
            MembershipModel.account_id == id).correlate_except(None))

在我尝试加入会员模型之前,这样可以正常工作。

query = AccountModel.query.join(MembershipModel)
# ProgrammingError: subquery uses ungrouped column "membership.account_id" from outer query

我可以通过追加来解决这个问题:

query = query.group_by(MembershipModel.account_id, AccountModel.id)
# resolves the issue

但我真的不想这样做。我希望它是自己的岛屿,忽略查询正在做的任何事情,只关注返回该特定行的帐户ID的成员资格数。

我可以对column_property做些什么来使其更强大,更少依赖于父查询的作用?

1 个答案:

答案 0 :(得分:2)

MembershipModel传递给correlate_except()而不是None,如文档中所述here。您的当前方法允许省略子查询的FROM子句中的所有内容,如果它可以与封闭查询相关联。当您加入MembershipModel时,它将在封闭查询中可用。

这是一个简化的例子。给定2个模型AB

In [2]: class A(Base):
   ...:     __tablename__ = 'a'
   ...:     id = Column(Integer, primary_key=True, autoincrement=True)
   ...:     

In [3]: class B(Base):
   ...:     __tablename__ = 'b'
   ...:     id = Column(Integer, primary_key=True, autoincrement=True)
   ...:     a_id = Column(Integer, ForeignKey('a.id'))
   ...:     a = relationship('A', backref='bs')
column_property上的

和2 A个定义:

In [10]: A.b_count = column_property(
    select([func.count(B.id)]).where(B.a_id == A.id).correlate_except(B))

In [11]: A.b_count_wrong = column_property(
    select([func.count(B.id)]).where(B.a_id == A.id).correlate_except(None))

如果我们只查询A,那么一切都很好:

In [12]: print(session.query(A))
SELECT a.id AS a_id, (SELECT count(b.id) AS count_1 
FROM b 
WHERE b.a_id = a.id) AS anon_1, (SELECT count(b.id) AS count_2 
FROM b 
WHERE b.a_id = a.id) AS anon_2 
FROM a

但是如果我们加入B,第二个属性会错误地将B与封闭查询相关联,并完全省略FROM子句:

In [13]: print(session.query(A).join(B))
SELECT a.id AS a_id, (SELECT count(b.id) AS count_1 
FROM b 
WHERE b.a_id = a.id) AS anon_1, (SELECT count(b.id) AS count_2 
WHERE b.a_id = a.id) AS anon_2 
FROM a JOIN b ON a.id = b.a_id