3

値を返す必要がある場合 (つまり、WHERE で使用されない場合)、SQLAlchemy でサブクエリを実行するための適切な構文を理解するのに苦労しています。

私は宣言的アプローチを使用しています。

次の 2 つのモデルが使用されています。

class ProjectInvoices(Base):
    InvoiceID = Column(Integer(unsigned=True), default=0, primary_key=True, autoincrement=True)
    MasterProjectID = Column(Integer(unsigned=True), index=True, nullable=False)
    ExpenseAmount = Column(Numeric(10, 2), default=0)
    HoursAmount = Column(Numeric(10, 2), default=0)
    IsVoid = Column(Boolean, default=0, index=True)
    IsSubmit = Column(Boolean, default=0, index=True)

class ProjectMasters(Base):
    MasterProjectID = Column(Integer(unsigned=True), default=0, primary_key=True, autoincrement=True)
    MasterProjectName = Column(Unicode(255))
    MasterProjectMemo = Column(UnicodeText)
    IsActive = Column(Boolean, default=0, index=True)

クエリのポイントは、サブクエリを使用して関連する請求書を合計することにより、各プロジェクトの現在の請求額を決定することです。これが単なる結合ではなくサブクエリで行われている理由は他にもあるため、サブクエリの問題を解決する必要があります。

これは、現在の SA クエリの例です。

sqry = session.query(
  func.sum(
    func.ifnull(ProjectInvoices.ExpenseAmount, 0) 
    + func.ifnull(ProjectInvoices.HoursAmount, 0))).label('billed_total')
).filter(and_(ProjectInvoices.IsVoid == 0, ProjectInvoices.IsSubmit == 1)
).subquery()

result = session.query(
  ProjectMasters.MasterProjectID, 
  ProjectMasters.MasterProjectName, 
  sqry.columns.billed_total.label('invoice_total')
).filter(ProjectMasters.IsActive == 1).all()

私はこれが恥ずかしい単純になるだろうと感じていますが、これを機能させるためにコードを解読することはできないようです.

私は見つけることができるほぼすべてのサンプルを試しましたが、結果はまちまちです。.correlate() 引数を省略すると、次のエラーが表示されます。

'Alias' object has no attribute 'MasterProjectID'

また、次のステートメントを subquery() の最後に追加しようとしましたが、うまくいきませんでした。

.correlate(ProjectMasters.MasterProjectID, ProjectInvoices.MasterProjectID)

相関引数を含めると、次のエラーが表示されます。

TypeError: Boolean value of this clause is not defined

事前に助けてくれてありがとう...

4

1 に答える 1

6

通常、私はcolumn_propertyそのような要件を処理するために a を使用します。

class ProjectMasters(Base):
    ...

    billed_total = column_property(
        select(
            [func.sum(
                func.coalesce(ProjectInvoices.ExpenseAmount, 0)
                + func.coalesce(ProjectInvoices.HoursAmount, 0)
            )],
            and_(
                MasterProjectID == ProjectInvoices.MasterProjectID,
                ProjectInvoices.IsVoid == False,
                ProjectInvoices.IsSubmit == True,
            ),
        ).label('billed_total'),
        deferred=True,
    )

その後、通常の属性のように使用できます。

result = session.query(
    ProjectMasters.MasterProjectID, 
    ProjectMasters.MasterProjectName, 
    ProjectMasters.billed_total.label('invoice_total'),
).filter(ProjectMasters.IsActive == 1).all()
于 2011-10-17T03:03:28.140 に答える