使用 SQLAlchemy 生成 sql 子查询作为 select 语句中的列
Generate sql with subquery as a column in select statement using SQLAlchemy
有没有办法让 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
您可以这样做,但它的工作方式与您编写它的方式完全不同。您可以根据与 tab2 的关系创建 Tab1 的 属性(假设 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'))
然后你可以添加类似
的内容
@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 answer and more docs。
完成此操作后,您可以在此 属性 上进行过滤,就像任何其他基于列的过滤一样。
如果您经常需要这个,and/or 计数是您的 Tab1
模型的组成部分,您应该使用其他答案中描述的混合 属性。另一方面,如果您只需要一个查询就需要这个,那么您可以使用 Query.label()
, or Query.as_scalar()
:
创建标量子查询
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它所能做的。
有没有办法让 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
您可以这样做,但它的工作方式与您编写它的方式完全不同。您可以根据与 tab2 的关系创建 Tab1 的 属性(假设 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'))
然后你可以添加类似
的内容@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 answer and more docs。
完成此操作后,您可以在此 属性 上进行过滤,就像任何其他基于列的过滤一样。
如果您经常需要这个,and/or 计数是您的 Tab1
模型的组成部分,您应该使用其他答案中描述的混合 属性。另一方面,如果您只需要一个查询就需要这个,那么您可以使用 Query.label()
, or Query.as_scalar()
:
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它所能做的。