web-dev-qa-db-ja.com

SQLAlchemyを使用して、selectステートメントの列としてサブクエリを使用してSQLを生成します

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)

PostgreSQL9.3と古いバージョンのSQLAlchemy0.9.8を使用しています

11
Antigluk

これが頻繁に必要な場合、および/またはカウントが_Tab1_モデルの不可欠な部分である場合は、他の回答で説明されているようなハイブリッドプロパティを使用する必要があります。一方、これが1つのクエリに対してのみ必要な場合は、 Query.label() または 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)
_

サブクエリは 自動的に相関します それが囲むクエリから何ができるか。

7
Ilja Everilä

これを行うことはできますが、それはあなたがそれを書いた方法とはまったく異なる方法で機能します。 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))

この回答 および その他のドキュメント のように、親モデルに。

これを実行すると、他の列ベースのプロパティと同じように、このプロパティでフィルタリングできます。

3
jwg