使用SQLAlchemy在select语句中将子查询作为列生成sql

2024-05-12 19:00:06 发布

您现在位置:Python中文网/ 问答频道 /正文

是否有方法使SQLAlchemy生成具有自定义列的查询,该自定义列是与当前行相关联的子查询:

SELECT
 tab1.id,
 tab1.col1, 
 ...,
 (
     SELECT count(1) FROM tab2 
     WHERE tab2.tab1_id = tab1.id
     GROUP BY tab2.col1
 ) as cnt
FROM tab1
WHERE ...
LIMIT 100

使用ORM API?

session.query(Tab1, ?(subquery for additional column)?).filter(...).limit(100)

我使用的是PostgreSQL 9.3和旧版本的SQLAlchemy 0.9.8


Tags: 方法fromidbysqlalchemyascountgroup
2条回答

如果您经常需要这样做,并且/或者计数是Tab1模型不可分割的一部分,那么您应该使用混合属性,如另一个答案中所述。另一方面,如果您只需要一个查询,那么您可以使用^{}^{}创建标量子查询:

count_stmt = session.query(func.count(1)).\
    filter(Tab2.tab1_id == Tab1.id).\
    group_by(Tab2.col1).\
    label('cnt')

session.query(Tab1, count_stmt).filter(...).limit(100)

子查询将automatically correlate它可以从封闭查询中得到什么。

你可以这样做,但它的工作方式与你写的完全不同。可以创建Tab1的属性,该属性取决于与tab2的关系(假设tab2.tab1_id是外键,它应该是外键)。

你的模特看起来是这样的:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))

根据the docs on relationships

然后你可以添加

@hybrid_property
def number_of_children(self):
    if self.children:
        return len(self.children)
    return 0

@number_of_children.expression
def number_of_children(cls):
    return (select([func.count(Child.id)])
            .where(Child.cover_id == cls.id))

到父模型,按照this answermore docs

完成此操作后,可以使用与任何其他基于列的属性相同的属性进行筛选。

相关问题 更多 >